当使用JavaScript API时,您还可以实现加密文档处理、签名刷新、重试、UI设置、全屏等功能,以及获取到预览文档渲染的相关信息,方便查看相关数据。

全屏预览支持

在嵌套预览引擎的父页面中,在iframe上添加allowfullscreen属性,即可支持全屏预览。

<iframe id="preview" src=[PreviewURL] allowfullscreen frameborder="0" scrolling="no"></iframe>
			

启用全屏预览方法:

function reqFullScreen(){
      var el = $('.preview')[0];
      var fn = el.requestFullScreen || el.webkitRequestFullScreen || el.mozRequestFullScreen || el.msRequestFullScreen;
      fn.call(el);
}
			

文字、演示页码跳转控制

// 跳转到某一页
sendMessage('logic.toPage', {
    pageIndex: 0 // 跳转页码,从0开始
});

// 跳转到上一页
sendMessage('logic.prevPage');

// 跳转到下一页
sendMessage('logic.nextPage');
			

文字、演示预览界面 UI 自定义

sendMessage('setConfig', {
  writerCustomStyle: function(isMobile) {
    if (!isMobile) {
      return {
        // 预览容器上边距
        containerMarginTop: 30,
        // 预览容器下边距
        containerMarginBottom: 30,
        // 容器背景色
        containerBackground: '#000000',
        // 页与页之间的距离
        pageSpacing: 20,
        // 每页的阴影样式
        pageShadow: '0px 0px 6px 0px rgba(0, 0, 0, 0.3)',
        // 每页的边框样式
        pageBorder: 'none',
        // 放大缩小按钮容器样式
        scale: {/* style注意这里的样式写法跟css文件样式写法一样,比如vertical-align:middle */},
        // 放大缩小按钮样式
        scaleBtn: {/* style注意这里的样式写法跟css文件样式写法一样,比如vertical-align:middle */},
        // 缩小按钮样式
        scaleShrink: {/* style注意这里的样式写法跟css文件样式写法一样,比如vertical-align:middle */},
        // 缩小按钮字符
        scaleShrinkText: '',
        // 缩小按钮不可点击样式
        scaleShrinkDisable: {/* style注意这里的样式写法跟css文件样式写法一样,比如vertical-align:middle */},
        // 放大按钮样式
        scaleMagnify: {/* style注意这里的样式写法跟css文件样式写法一样,比如vertical-align:middle */},
        // 放大按钮字符
        scaleMagnifyText: '',
        // 放大按钮不可点击样式
        scaleMagnifyDisable: {/* style注意这里的样式写法跟css文件样式写法一样,比如vertical-align:middle * /},
        // 缩放比例文字
        scaleText: {/* style注意这里的样式写法跟css文件样式写法一样,比如vertical-align:middle */},
        // 缩放组件元素排序
        scaleSort: ['shrink', 'text', 'magnify'] // shrink缩小,text文字,magnify放大
      }
    } else {
      return {
        pageBorder: '1px solid #d2d5d8'
      };
    }
  }
});

// 演示预览自定义样式
sendMessage('setConfig', {
  powerpointCustomStyle: function(isMobile) {
    if (!isMobile) {
      return {
        // 隐藏翻页按钮
        paginationDisplay: false,
        // 隐藏全屏按钮
        fullScreenButtonDisplay: false,
        // 预览容器上边距
        containerMarginTop: 30,
        // 预览容器下边距
        containerMarginBottom: 30,
        // 容器背景色
        containerBackground: '#000000'
      };
    } else {
      return {};
    }
  }
});
			

自定义错误提示界面

在iframe外框监听错误消息,自行处理报错的UI逻辑。

sendMessage("setConfig", {
  enableMessageUI: false
});

window.addEventListener('message', function(e) {
  var res = JSON.parse(e.data);
    switch(res.action) {
    case 'message.error':
      toast(i18n(res.data.result));
      break; 
    }
}, false);
			

设置加密文件解密流程

监听message.error事件, 处理展示密码输入相关UI逻辑,然后用户输入密码后,携带密码再次提交转换任务,服务端根据提交的密码执行解密流程,生成一个新的预览地址,浏览器重新设置iframe的src属性为新的预览地址。如果解密失败,子页面会重新抛出aliyunPasswordInvalid错误,重新输入密码即重复以上流程即可。

sendMessage("setConfig", {
    enableCheckPasswordLogic: false
});
			
var isFirstTime = false;
window.addEventListener('message', function(e) {
  var res = JSON.parse(e.data);
    switch(res.action) {
    case 'message.error':
      if (res.data.result === 'aliyunPasswordInvalid') {
        if (isFirstTime) {
          // 显示密码框
          // your code
          isFirstTime = false;
        } else {
          // 提示密码错误
          // your code
        }
    }
      break;
    }
}, false);
			

刷新签名

当用户本地临时访问凭证过期时,无法继续预览文档,此时需要刷新签名。首先监听子页面抛出的logic.refreshToken 事件,然后获取相关token信息后通过发送logic.setToken消息设置相关token信息,刷新iframe页面签名。

window.addEventListener('message', function(e) {
  var res = JSON.parse(e.data);
    switch(res.action) {
    case 'logic.refreshToken':
        // 重新获取token的逻辑请自行实现
      $.ajax(...).then(function(data){
        sendMessage('logic.setToken', {
          region: data.region,
          accessKeyId: data.accessKeyId,
          accessKeySecret: data.accessKeySecret,
          stsToken: data.stsToken,
          bucket: data.bucket
        });
      });
    break;
    ...
  }
}, false);
			

重试机制

如果浏览器预览出错,可以设置重试逻辑,尝试重新获取OSS预览文档信息,提高用户可以预览的成功率。

sendMessage('setConfig', {
  couldRetry: function(tryCount) {
    //tryCount当前已经重试的次数
    return new Promise(function(resolve) {
      if (tryCount > 35) {
        // 最多重试次数
        resolve(false);
      } else {
        var tryDelay = 0;
        if (tryCount < 2) {
          // 0 - 1
          tryDelay = 250;
        } else if (tryCount <= 11) {
          // 2 - 11
          tryDelay = 500;
        } else {
          // 12 - 35
          tryDelay = 1000;
        }
        setTimeout(function () {
          resolve(true); // 执行重试
        }, tryDelay);
      }
    });
  }
});
			

广告配置

//文字Word (演示移动端)
sendMessage('setConfig', {
  wordAd: function(pageIndex, total) {
  //pageIndex当前页数total总页数,接入方可以通过这些参数设计广告显示逻辑
    return {
      type: 'iframe', // iframe或者img
      src: iframeData.xxx, //函数中所有变量必须通过setData传递,并通过iframeData来使用
      href: iframeData.xxx, //跳转地址 
      width: 1090, //宽度
      height: 200, //高度
      closeBtn: true //是否显示关闭广告按键
    };
  }
});
//表格Excel
sendMessage('setConfig', {
  etAd: function() {
    return {
      type: 'iframe',
      src: 'http://xxxx',
      href: '',
      width: 1090,
      height: 200,
      closeBtn: true
    }
  }
});
//演示 PowerPonit(web端)
sendMessage('setConfig', {
  wppAd: function() {
      return {
      type: 'iframe',
      src: 'http://xxxx',
      href: '',
      width: 1090,
      height: 200,
      closeBtn: true
    }
  }
});
			
注意 若data为function,则函数中引用的变量必须在此之前通过setData来传递到子页面。

本地签名时间校准

OSS SDK签名时默认会使用本地时间,如果用户本地时间与服务器时间相差超过15分钟则会导致签名验证失败,此时可手动设置强制本地使用服务器时间签名,而获取服务器时间的逻辑则由用户自行处理。

sendMessage("setConfig", {
  timestamp: {
    serverTime: 1540881763,  // 服务器当前时间,单位:秒
    expires: 3600 // 签名有效期,单位:秒,默认:1800
  }
});
			

预览信息获取

在iframe外层监听message,可以得到预览页面抛出的信息,信息体也为JSON格式字符串, 如{"action":"page.readPage", "data":{"pageIndex":5}},action为事件名,data为抛出的数据。

window.addEventListener('message', function(e) {
  var res = JSON.parse(e.data);
  // res.action
  // res.data
})
			

记录当前浏览页码

监听action为page.readPage时,会返回当前浏览页数data.pageIndex,接入方自行存储该值后,下次打开相同页面只需将其赋值于iframe url中的pageIndex参数即可跳转到上次浏览的页码,以实现从历史记录继续浏览。

{
  "action": "page.readPage",
  "data": {
    "pageIndex": 0
  }
}
			

获取meta.json信息

{
  action: "preview.meta", //当前页面执行状态
  data: {
    version: "xxx", //数据版本号
    epc: "xxx", //预览渲染的页数
    pc: "xxx",  //文档实际的页数
    pro: "xxx",  //文件类型
    ...
  }
}
			

错误事件说明

当发生错误时,父级窗口会接收到以下数据结构JSON字符串消息。

{
  action: 'message.error',
  data: {
    result: 'aliyunOpenFileFail',
    data: {
    // 错误细节
    }
  }
}
			

其中action字段为message.error,是固定值result字段为具体错误类型的说明,如下所示。

  • aliyunOpenFileFail:打开文档失败
  • aliyunUnsupportFile:不支持的文件类型
  • aliyunRequstFail:前端请求静态资源失败,包括签名错误等,具体信息会有data数据返回
  • aliyunQueryParamInvalid:页面必传参数缺失
  • aliyunRequestTimeout:资源加载超时
  • aliyunRenderEngineTooOld:js渲染引擎版本过旧
  • aliyunPasswordInvalid:密码错误,需要处理密码重试的逻辑

获取渲染页面关键信息

首先父级窗口会接收到以下数据结构JSON字符串消息。

{
  action: 'page.getBaseInfoFromServerDone', //当前页面执行状态
  data: {
    startTime: 1111,//开始时间
    endTime: 1111, //结束时间
    useTime: 1111, //花费时间
    pageStartTime: 1111 //预览页面开始时间
  }
}
			
事件 说明
getBaseInfoFromServerDone 获取页面基本信息
getSheetInfoFromServerDone 获取表格基础信息
getPageInfoFromServerDone 获取单页信息,{pageIndex: 0, .....}
firstRendered 首屏渲染完成{startTime, pageStartTime}
timing 请参见Timing格式
说明 所有page.*Done格式的事件data都有以下参数, {startTime: 开始时间, endTime: 结束时间, useTime: 花费时间, pageStartTime: 页面开始时间} ,时间都是毫秒为单位,上面表格描述的事件中,page.xxxDone就会有page.xxx事件,page.xxx为page.xxxDone开始执行的事件,page.xxx少了endTime,useTime字段。

timing格式如下所示。

// t为performance.timing
{
  // 页面加载完成的时间
  loadPage : t.loadEventEnd - t.navigationStart,
  // dom解析事件
  domReady : t.domComplete - t.responseEnd,
  // 重定向的时间
  redirect : t.redirectEnd - t.redirectStart,
  // DNS查询时间
  lookupDomain : t.domainLookupEnd - t.domainLookupStart,
  // TTFB即Time To First Byte的意思
  ttfb : t.responseStart - t.navigationStart,
  // 内容加载完成的时间
  request : t.responseEnd - t.requestStart,
  // 执行onload回调函数的时间
  loadEvent : t.loadEventEnd - t.loadEventStart,
  // DNS缓存时间
  appcache : t.domainLookupStart - t.fetchStart,
  // 卸载页面的时间
  unloadEvent : t.unloadEventEnd - t.unloadEventStart,
  // TCP建立连接完成握手的时间
  connect : t.connectEnd - t.connectStart,
  timing: t
}