当使用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);
      }
    });
  }
});
            

自定义广告

注意 如果data为function,则函数中引用的变量必须在此之前通过setData传递到子页面。
//文字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(移动端和WEB端)。
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
    }
  }
});
            

校准本地签名时间

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 //预览页面开始时间。
  }
}
            
说明
  • 所有page.*Done格式的事件data都包含 {startTime: 开始时间, endTime: 结束时间, useTime: 花费时间, pageStartTime: 页面开始时间} 参数,时间的单位均毫秒。
  • 下表描述的事件中,page.xxxDone均会有page.xxx事件,page.xxx事件为page.xxxDone开始执行的事件,page.xxx中相对于page.xxxDone缺少endTime和useTime参数。
事件 说明
getBaseInfoFromServerDone 获取页面基本信息。
getSheetInfoFromServerDone 获取表格基础信息。
getPageInfoFromServerDone 获取单页信息,{pageIndex: 0, .....}。
firstRendered 首屏渲染完成{startTime, pageStartTime}。
timing 更多信息,请参见Timing格式

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
}