全部产品
云市场

文档预览

更新时间:2019-08-15 15:38:57

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

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

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

1. 预览原理

原理

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

iframe

2. 准备工作

(1) 跨域配置

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

cors

(2) OSS临时授权访问

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

  • 公共读

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

  • 私有读

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

3. 预览引擎

(1) 预览接入方式介绍

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

1. URL 参数预览

2. JavaScript API 预览

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

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

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

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

(2) 方式一: URL 参数预览

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

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

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

预览 URL 示例

  1. https://preview.imm.aliyun.com/index.html
  2. ?url=https://yourid-dev-imm.oss-cn-shanghai.aliyuncs.com/paxos.pptx/output //转换结果地址,无需在output后加'/'
  3. &accessKeyId=STS.AAAA //STS 返回的 AccessKeyId,注意 access 小写
  4. &accessKeySecret=BBBB //STS 返回的 AccessKeySecret,注意 access 小写
  5. &stsToken=CCCC //CCCC 是 encode(STS返回的 SecurityToken)得到的结果,不直接使用
  6. &region=oss-cn-shanghai //转换数据所在桶的 region,注意加 oss 前缀
  7. &bucket=bucket-name //转换数据所在桶
  8. &...

参数解释

参数名 类型 是否必填 描述
url String 文档格式转换后的向量文件所在目录, 注意:无需在目录后加/
region String 私有读时必填 OSS 数据所在region,例如oss-cn-shanghai, 注意:添加 OSS 前缀
accessKeyId String 私有读时必填 从 STS 获取的访问 OSS 参数
accessKeySecret String 私有读时必填 从 STS 获取的访问 OSS 参数
stsToken String 私有读时必填 从 STS 获取的访问 OSS 参数
bucket String 私有读时必填 OSS 数据所在桶
endpoint String 使用与 OSS 桶绑定的用户域名进行预览,使用此参数时无需传递 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 如下:

  1. <html>
  2. <head>
  3. <meta charset="UTF-8">
  4. <!-- 建议禁用外框浏览器自带的缩放 -->
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,user-scalable=no">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title></title>
  8. <style>
  9. * {
  10. box-sizing: border-box;
  11. }
  12. html, body {
  13. padding: 0;
  14. margin: 0;
  15. height: 100%;
  16. /* 防止双击缩放 */
  17. touch-action: manipulation;
  18. }
  19. .main {
  20. display: flex;
  21. flex-direction: column;
  22. height: 100%;
  23. }
  24. #aliyunPreview {
  25. flex: 1;
  26. }
  27. </style>
  28. <script type="text/javascript" charset="utf-8">
  29. function json2str(obj) {
  30. return JSON.stringify(obj, function(key, val) {
  31. if (typeof val === 'function') {
  32. val = val.toString();
  33. }
  34. return val;
  35. });
  36. };
  37. window.sendMessage = function(action, data) {
  38. var iframe = document.getElementById('aliyunPreview');
  39. iframe.contentWindow.postMessage(json2str({ action: action, data: data }), '*');
  40. };
  41. window.addEventListener('message', function(e) {
  42. try {
  43. var res = JSON.parse(e.data);
  44. } catch(err) {
  45. return;
  46. }
  47. switch (res.action) {
  48. case 'preview.ready':
  49. window.sendMessage('preview.init', {
  50. url: '',
  51. region: '',
  52. bucket: '',
  53. accessKeyId: '',
  54. accessKeySecret: '',
  55. stsToken: ''
  56. });
  57. break;
  58. }
  59. }, false);
  60. //禁止双指缩放手势
  61. document.addEventListener('gesturestart', function (e) {
  62. e.preventDefault();
  63. });
  64. </script>
  65. </head>
  66. <body>
  67. <iframe
  68. allowfullscreen
  69. id="aliyunPreview"
  70. frameborder="0"
  71. src="https://preview.imm.aliyun.com/index.html"
  72. ></iframe>
  73. </body>
  74. </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 - 文档格式转换后的向量文件所在目录, 注意:无需在目录后加/
region String 私有读时必填 - OSS 桶所在区域
bucket String 私有读时必填 - OSS 桶的名称
accessKeyId String 私有读时必填 - OSS 桶访问的钥匙 ID
accessKeySecret String 私有读时必填 - OSS 桶访问的钥匙 Secret
stsToken String 私有读时必填 - OSS 桶访问的令牌
endpoint String - 使用与 OSS 桶绑定的域名,使用此参数时无需传递 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 形式在子页面中访问,可多次调用。
  1. sendMessage("setData", {
  2. // 需要在子页面中用到的数据
  3. });

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属性来禁止父级窗口缩放

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

    禁用双击缩放手势

    1. body {
    2. touch-action: manipulation;
    3. }

    禁止双指缩放手势

    1. document.addEventListener('gesturestart', function(e) {
    2. e.preventDefault();
    3. });
  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&...即可解决,推荐第二种方法较快捷。