React 实现 PDF 预览
embed标签实现PDF预览
这种方式虽然简单但是不兼容移动端,实现如下:
<embed
src="path/to/pdf"
type="application/pdf"
style={{ width: '100vw', height: '100vh' }}
></embed>
react-pdf组件
这种方式兼容PC和移动,但是移动端显示不好查看,样式调整比较麻烦。
分页只能自己实现,组件本身不提供分页。
注:如果您使用 Browserify 或打包工具,则必须自行确保将该pdf.worker.js文件pdfjs-dist/build复制到项目的输出文件夹中。
实现如下,示例代码中的pdf.worker.min.js使用的是CDN资源,生产环境可能出现加载不到导致预览失败的情况,所以最好下载到本地,从本地引用:
import { Document, Page, pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;
export default ()=>{
const [numPages, setNumPages] = useState(0);
const [pageNumber, setPageNumber] = useState(1);
const onDocumentLoadSuccess = ({ numPages }:any) => {
setNumPages(numPages);
}
return <Document
className="className"
file="path/to/pdf"
loading={<div className={styles.loading}><Spin size="large" /></div>}
onLoadSuccess={onDocumentLoadSuccess}
>
<Page pageNumber={pageNumber} />
</Document>
{"自定义pagination分页,通过setPageNumber实现翻页"}
}
更详细的用法附上github地址: react-pdf
阿里云 IMM 服务实现文件在线预览,需要服务端配合(收费)
支持的文档格式
文档预览支持的文档类型和格式如下表所示。
文档类型 | 文件扩展名 |
---|---|
文字 | doc、dot、wps、wpt、docx、dotx、docm、dotm、rtf、txt |
表格 | xls、xlt、et、xlsx、xltx、csv、xlsm、xltm |
演示 | |
准备工作
当访问的OSS Bucket域名与预览引擎的域名不同时,需要在OSS控制台将预览服务域名添加到存储转换后文档的OSS Bucket的跨域访问列表中。具体操作,请参见设置跨域访问。
预览流程
在服务端分别封装GetWebofficeURL和RefreshWebofficeToken接口。
通过JS-SDK将返回的预览地址挂载到HTML块状元素中并设置AccessToken。
服务端封装接口
在服务端需要分别封装GetWebofficeURL和RefreshWebofficeToken接口,用于获取编辑地址和AccessToken,方便前端直接调用。
1.调用GetWebofficeURL接口,获取协作地址。返回结果示例如下:
{
"RefreshToken": "306ffe61897443c8909aaad325********",
"RequestId": "D807F412-1EE0-44E0-A60F-47C27B4046CF",
"AccessToken": "7f9b6ba5baef4c7d80f837d4c9********",
"RefreshTokenExpiredTime": "2021-04-21T06:48:10.161355914Z",
"WebofficeURL": "https://office-cn-shanghai.imm.aliyuncs.com/office/p/9eea88df758a75b6308358500a9e141ccf3b7629?_w_tokentype=1",
"AccessTokenExpiredTime": "2021-04-20T07:18:10.161355914Z"
}
2.调用RefreshWebofficeToken接口,刷新AccessToken。
AccessToken具有时效性,当过期后前端需要调用服务端RefreshWebofficeToken接口重新刷新AccessToken,所以需要在服务端封装此接口。调用此接口的返回结果格式和调用GetWebofficeURL接口的相同。
前端JS-SDK使用
1.引入JS-SDK。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Demo</title>
</head>
<body>
<script src="https://g.alicdn.com/IMM/office-js/${x.y.z}/aliyun-web-office-sdk.min.js"></script>
<script>
console.log('引入后可以开始使用JS-SDK了!');
console.log(aliyun); //全局变量名。
</script>
</body>
</html>
以上示例中${x.y.z}表示最新版本号,请根据实际填写.
2.接入WebOffice。
通过在服务端封装的GetWebofficeURL接口获取tokenInfo对象。假设tokenInfo对象和调用GetWebofficeURL接口返回的结构一致。
如下示例以服务端封装的GetWebofficeURL接口为/getTokenInfo举例说明。
//获取协作地址和AccessToken。
var tokenInfo = await $.get('http://example.com/getTokenInfo')
let instance = aliyun.config({
url: tokenInfo.WebofficeURL //设置文档协作URL地址。
})
//设置AccessToken。
instance.setToken({
token: tokenInfo.AccessToken
})
3.自定义Office(iframe)挂载点。
说明 在DOMContentLoaded事件被触发后,请确保挂载节点存在再执行初始化操作。
iframe(#iframe)默认会挂载到body下,可根据需要自定义iframe(#iframe)的挂载点。
<div id="container"></div>
aliyun.config({
mount: document.querySelector('#container'),
url: '文档协作URL地址' //即步骤2示例中的文档协作URL地址(tokenInfo.WebofficeURL)。
})
如果需要对iframe对象做特殊处理,可以通过JS-SDK实例化对象快速获取到iframe的DOM(Document Object Model)对象。
var instance = aliyun.config({
mount: document.querySelector('#container')
//...
})
console.log(instance.iframe)
3.设置令牌(Token)。
- 在获取协作地址后,需要设置令牌才能在线协作。
- 每次刷新令牌后,也需要通过此方法设置令牌。
//根据业务需求通过异步请求或者模板输出的方式获取token。 var token = 'yourToken'; //设置token。 instance.setToken({ token: token, timeout: 10 * 60 * 1000, //必须设置。token的超时时间,单位为ms。以10分钟示例说明。 })
5.超时更新令牌(Token)。
通过在服务端封装的RefreshWebofficeToken接口获取tokenInfo对象。假设tokenInfo对象和调用RefreshWebofficeToken接口返回的结构一致。
您可以通过传入获取Token的函数,在Token超时时,JS-SDK会自动调用传入的函数重新获取Token,返回一个promise或者object。
如下示例以服务端封装的GetWebofficeToken接口为/refreshTokenInfo举例说明。
//缓存上次的tokenInfo,用于刷新token。
let lastTokenInfo = tokenInfo
//获取token函数。
const refreshToken = async () => {
//业务处理逻辑,调用服务端封装的refreshToken接口。
let tokenInfo = await $.get('http://example.com/refreshTokenInfo',{
RefreshToken: lastTokenInfo.RefreshToken,
AccessToken: lastTokenInfo.AccessToken,
//....
})
lastTokenInfo = tokenInfo
return {
token: tokenInfo.AccessToken, //必须设置。
timeout: 10 * 60 * 1000, //必须设置。token超时时间,单位为ms。可配合refreshToken配置函数使用,在超时前调用refreshToken重新刷新token。
}
}
//配置超时获取token函数。
aliyun.config({
//...
refreshToken
})
参考文档:IMM 用户指南