文档预览是在文档格式转换基础上提供的功能,通过将输入文档转换为JPG、PNG等输出格式,您可以快速搭建自己的文档预览。

同时,智能媒体管理服务推荐您使用VECTOR输出格式,然后通过智能媒体管理提供的前端渲染引擎,实现更易用、功能更强大、定制化的文档预览效果。

下面重点跟大家讲解向量模式VECTOR的文档预览实现。

1.预览原理

  1. 上传需要预览的文件存储在对象存储 OSS中。
  2. 调用智能媒体管理的文档格式转换接口,将要预览的源文件按转换为向量格式输出到指定的OSS目录。
  3. 将智能媒体管理提供的预览引擎preview.imm.aliyuncs.com/index.html?url=[TgtUri]通过HTML的<iframe>标签嵌入到用户自己的页面或者Web App中进行文档预览。其中TgtUri为预览文件在OSS的http(s)路径,需要通过QueryString参数传入,如下图所示。

2.准备工作

(1)跨域配置

由于被访问的OSS Bucket域名同上述预览引擎的域名不同,所以直接访问会存在跨域问题。此时用户需要在OSS 控制台将预览服务域名添加到存储转换后文档OSS Bucket的跨域访问列表中,具体操作路径为OSS控制台 > 基础设置 > 跨域设置 > 创建规则,需要创建的跨域规则如下图。

(2)OSS临时授权访问

由于预览引擎需要从用户的OSS Bucket读取转换后的文档,受用户Bucket读取权限(了解OSS读写权限控制)影响,预览引擎读取文档方式也不尽相同。

  • 公共读

    如果Bucket设置为公共读,则此Bucket中的所有文件无需任何授权即可读取,无需传入访问凭证相关的参数即可预览,设置公共读前请确认是否有相关安全风险。

  • 私有

    此时需要通过OSS STS获取该文件临时的访问权限,获取临时访问凭证之后传递给预览引擎,预览引擎通过凭证获取相关权限,从而实现文档预览。临时访问凭证一般包括AccessKeyId | AccessKeySecret | SecurityToken,如何获取临时访问权限,请参见STS临时授权访问OSS

3.预览引擎

(1)预览接入方式介绍

预览引擎支持两种预览方式:

  • URL参数预览
  • JavaScript API预览

两种方式的优缺点对比如下:

方式 优点 缺点
URL参数预览 快捷方便 相关临时授权凭证会暴露在iframe的URL地址上
JavaScript API预览 JavaScript API隐式传递参数,安全性较高 需要部分额外的前端编程工作

URL参数预览的优点是方便,但容易暴露预览地址。当用户bucket为私有读并在签名有效期内,用户只要把对应的URL从iframe src属性中复制出来即可分享给别人,对安全性要求较高的业务不建议这种方式。通过JavaScript API传递参数的方式,由于iframe地址不含签名,因此用户即使复制了URL也无法预览。用户可根据应用场景自行选择预览方式,推荐使用API方式。

下面分别介绍两种预览的具体实现。

方式一:URL参数预览

URL参数预览即通过URL QueryString将必要的参数传递给预览引擎,预览引擎获取相关参数后在页面上展示出文档,一个完整的预览URL格式如下所示。

https://preview.imm.aliyuncs.com/index.html?url=[url]&accessKeyId=[accessKeyId]&accessKeySecret=[accessKeySecret]&stsToken=[stsToken]&bucket=[bucket]&region=[region]
			

其中https://preview.imm.aliyuncs.com/index.html是智能媒体管理服务提供的预览引擎地址,?后面的参数是预览文档的信息,如果不提供必须的参数,则会预览失败。

  • 预览URL示例
    https://preview.imm.aliyuncs.com/index.html
    ?url=https://yourid-dev-imm.oss-cn-shanghai.aliyuncs.com/paxos.pptx/output    //转换结果地址,无需在output后加/
    &accessKeyId=STS.AAAA    //STS返回的AccessKeyId,注意access小写
    &accessKeySecret=BBBB    //STS返回的AccessKeySecret,注意access小写
    &stsToken=CCCC    //CCCC是encode(STS返回的SecurityToken)得到的结果,不直接使用
    &region=oss-cn-shanghai    //转换数据所在bucket的region,注意加oss前缀
    &bucket=bucket-name    //转换数据所在bucket
    &...
    					
  • 参数解释
    参数名 类型 是否必填 描述
    url String 文档格式转换后的向量文件所在目录。假设提交文档转换任务的TgtUri为 oss://your-bucket/paxos.pptx/output 那么url为https://your-bucket.oss-{region}.aliyuncs.com/paxos.pptx/output
    注意 无需在目录后加/
    region String bucket私有时必填 OSS数据所在region,例如oss-cn-shanghai
    注意 请注意添加OSS前缀
    accessKeyId String bucket私有时必填 从STS获取的访问OSS bucket的访问密钥标识
    accessKeySecret String bucket私有时必填 从STS获取的访问OSS bucket的访问密钥
    stsToken String bucket私有时必填 从STS获取的访问OSS bucket的安全令牌
    bucket String bucket私有时必填 OSS数据所在bucket
    endpoint String 使用与OSS bucket绑定的用户域名进行预览,使用此参数时无需传递bucket和region
    pageIndex Int 从指定的页码开始预览
    serverTime Int 服务器当前时间,单位:秒,用于校准本地OSS签名时的时间,避免本地与服务器时差大于15min导致签名失败
    expires Int 文档预览有效时间,单位:秒,默认:1800
    注意 其中参数url格式同OSS实际访问地址,如https://yourid-dev-imm.oss-cn-shanghai.aliyuncs.com/paxos.pptx/output,结尾无需加上/。

(3)方式二:JavaScript API预览

JavaScript API预览具有更好的安全性,并且提供了高级功能的配置(详见下一章文档预览JavaScript API),JavaScript API本质上通过postMessage将必要参数发送给预览引擎页并完成初始化工作,postMessage的浏览器兼容请参见此链接

JavaScript API预览Demo如下:

<html>
  <head>
    <meta charset="UTF-8">
    <!-- 建议禁用外框浏览器自带的缩放 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,user-scalable=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
    <style>
      * {
        box-sizing: border-box;
      }
      html, body {
        padding: 0;
        margin: 0;
        height: 100%;
        /* 防止双击缩放 */
        touch-action: manipulation;
      }
      .main {
        display: flex;
        flex-direction: column;
        height: 100%;
      }
      #aliyunPreview {
        flex: 1;
      }
    </style>
    <script type="text/javascript" charset="utf-8">
      function json2str(obj) {
        return JSON.stringify(obj, function(key, val) {
          if (typeof val === 'function') {
            val = val.toString();
          }
          return val;
        });
      };

      window.sendMessage = function(action, data) {
        var iframe = document.getElementById('aliyunPreview');
        iframe.contentWindow.postMessage(json2str({ action: action, data: data }), '*');
      };

      window.addEventListener('message', function(e) {
        try {
          var res = JSON.parse(e.data);
        } catch(err) {
          return;
        }

        switch (res.action) {
          case 'preview.ready':
            window.sendMessage('preview.init', {
              url: '',
              region: '',
              bucket: '',
              accessKeyId: '',
              accessKeySecret: '',
              stsToken: ''
            });
            break;
        }
      }, false);

      //禁止双指缩放手势
      document.addEventListener('gesturestart', function (e) {
        e.preventDefault();
      });
    </script>
  </head>
  <body>
    <iframe
      allowfullscreen
      id="aliyunPreview"
      frameborder="0"
      src="https://preview.imm.aliyuncs.com/index.html"
    ></iframe>
  </body>
</html>
			
  • 初始化流程

    为便于描述,以下称阿里云的iframe页面为子页面,嵌入该iframe的接入方页面称为父页面。

    1.子页面发送preview.ready事件。

    2.父页面接收preview.ready事件之后,发送preview.init事件以及传递初始化参数。

    3.子页面接收preview.init事件及其参数,并以此初始化渲染引擎。

  • 事件说明

    父页面向子页面发送消息,通过sendMessage(参考上面demo)完成,调用格式为sendMessage(action, data)

    参数名 类型 是否必填 描述
    action String 事件名称
    data Object 事件参数

    其中action可使用如下定义。

    • preview.init:父页面传递初始化子页面参数,可设置参数列表如下:
      参数名 类型 是否必填 默认值 描述
      url String - 文档格式转换后的向量文件所在目录。假设提交文档转换任务的TgtUri为 oss://your-bucket/paxos.pptx/output 那么url为https://your-bucket.oss-{region}.aliyuncs.com/paxos.pptx/output
      注意 无需在目录后加/
      region String bucket私有时必填 - OSS数据所在region,例如oss-cn-shanghai
      注意 请注意添加OSS前缀
      bucket String bucket私有时必填 - OSS bucket的名称,例如:your-bucket
      accessKeyId String bucket私有时必填 - 从STS获取的访问OSS bucket的访问密钥标识
      accessKeySecret String bucket私有时必填 - 从STS获取的访问OSS bucket的访问密钥
      stsToken String bucket私有时必填 - 从STS获取的访问OSS bucket的安全令牌
      endpoint String - 使用与OSS bucket绑定的域名,使用此参数时无需传递bucket和region
      copy Int 0 是否允许文字拷贝,可选值[0, 1],0 - 禁止,1 - 允许
      wmType Int 0 水印类型可选值[0, 1, 2]。
      • 0:关闭水印
      • 1:文字水印
      • 2:图片水印
      wmValue String - 水印值,wmType为1时,水印内容,wmType为2时,图片水印地址
      wmColor String rgba(192, 192, 192, 0.6) 水印颜色,RGBA值
      wmRotate Float -Math.PI / 4 水印角度
      wmFont String bold 20px Serif 水印字体
      wmHeight Int 170 水印高度
      wmWidth Int 195 水印宽度
    • setConfig:父页面设置子页面相关的渲染参数,具体支持的功能请参见文档预览JavaScript API
    • setData:用于传递参数变量,供setConfig中使用,函数中的变量以window.iframeData形式在子页面中访问,可多次调用。
    sendMessage("setData", {
      // 需要在子页面中用到的数据
    });
    
      //注意:sendMessage封装了postMessage,具体方法请参见上面的JavaScript API预览Demo中的代码。
    					

4. 预览页面提示错误码

错误码 描述
-1002 无效的AccessKeyId
-1003 无权限访问该文档
-1004 无效的STSToken
-1005 STSToken已过期
-1006 签名错误
-1007 Bucket未配置跨域
-1008 Refers配置错误
-1100 其他原因造成的错误

5. 支持的浏览器

  • Internet Explorer 10+ and Microsoft Edge
  • Google Chrome
  • Firefox
  • Safari
  • Opera

6. 常见问题以及解决方案

声明:以下方案仅为建议的通用解决方案,不保证百分百适用所有场景,不同的应用场景需要具体问题具体分析。

  1. iframe内部预览界面被遮挡问题
    • 禁止iframe滚动,设置iframe属性scrolling="no"(预览界面实现了局部滚动,可以放心把该属性设置为no)。
    • 通过flex布局来给iframe弹性高度或者通过js计算设置iframe一个具体高度值,不能用百分比。
  2. 父级窗口缩放导致预览界面变形问题怎么处理?

    遇到此问题则需要父级窗口禁用浏览器自带的缩放功能。

    • 安卓下解决方案

      安卓下通过设置viewport的user-scalable属性来禁止父级窗口缩放。

      <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
      							
    • iOS下解决方案

      禁用双击缩放手势

      body {
       touch-action: manipulation;
      }
      							

      禁止双指缩放手势

      document.addEventListener('gesturestart', function(e) {
       e.preventDefault();
      });
      							
  3. PPT预览全屏按钮在某些浏览器中消失如何处理?

    出现此问题时,您只需在iframe上添加allowfullscreen属性即可修复,加上此属性后PPT文件可支持全屏预览。

  4. IE 下通过location.href | window.open打开预览URL时,如果URL中包含复制功能参数&copy=1,则会被当做HTML实体解析为版权符号©=1,导致预览不成功怎么处理?

    这个问题是由于IE的经典bug导致,此时有两种解决方案:

    • 判断如果在IE浏览器中,在跳转前把&转义为HTML字符实体&amp;
    • &copy=1位置调整为紧跟url的第一个参数,如?copy=1&...即可解决,推荐第二种方法较快捷。