浏览器在线查看pdf的几种方法

浏览器在线查看pdf的几种方法

一月 23, 2021

浏览器在线查看pdf的几种方法

参考资料

  1. https://github.com/mozilla/pdf.js/issues/12066
  2. https://github.com/mozilla/pdf.js/tree/master/examples/learning
  3. https://blog.csdn.net/shentibeitaokong/article/details/80011900

目标

在后端返回pdf数据后能够实现pdf的在线查看,这里后端返回分为几种格式:

  1. ***.pdf为后缀静态资源链接
  2. 文件数据流形式
  3. base64形式

***.pdf为后缀静态资源链接

针对这种形式,最简单的思路是使用iframe标签的形式

1
2
3
<iframe src="****.pdf" >

</iframe>

当然也可以使用pdfjs,下面将统一讲解

使用pdfjs

使用pdfjs大致参考官方的examples

这里放个使用react的栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import react, { useEffect, useState } from 'react';
import './index.css';
import * as myPdfjs from 'pdfjs-dist';

// 特别注意!!!!!!!!!这里的版本必须对应
// npm install 下载的依赖有可能会版本不一致导致报错
// 报错的话,参考我的第一个参考链接
myPdfjs.GlobalWorkerOptions.workerSrc = `//cdn.bootcdn.net/ajax/libs/pdf.js/${myPdfjs.version}/pdf.worker.min.js`;
export default function App() {
// 替换成需要的pdf文件
const [pdfUrl, setPdfUrl] = useState('http://****.pdf');
const [canvanId, setCanvanId] = useState("pdf-" + parseInt(Math.random() * 10000));

useEffect(() => {
setViewDocument(myPdfjs, pdfUrl, canvanId)
},[]);

return (
<>
<div id={canvanId}>
</div>
</>
)
}

const setViewDocument = async (myPdfjs, pdfUrl, domId) => {
let pdfDocument = await getPdfDocument(myPdfjs, pdfUrl);
for(let i = 1; i <= pdfDocument._pdfInfo.numPages; i++){
setPdfDocument(domId, pdfDocument, i)
}
}

// 获取
const getPdfDocument = async (myPdfjs, pdfUrl) => {
let loadingTask = myPdfjs.getDocument(pdfUrl);
const pdfDocument = await loadingTask.promise;
await pdfDocument.dataLoaded;
return pdfDocument;
}

// 添加
const setPdfDocument = async (domId, pdfDocument, page) => {
pdfDocument.getPage(page).then(page => {
let scale = 2; // 缩放倍数
let viewport = page.getViewport({ scale: scale });
let mainDom = document.getElementById(domId);
mainDom.setAttribute("style", 'width:' + viewport.width + 'px')
let canvas = document.createElement("canvas");
let context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
let renderContext = {
canvasContext: context,
viewport: viewport,
};
page.render(renderContext);
mainDom.appendChild(canvas)
});
}

http://r.photo.store.qq.com/psc?/V51omi8H2ZybVP1W54I94cQfjz0BuScw/45NBuzDIW489QBoVep5mcSxUmTZ9Nyu02gmc4lRzgvxgnK.e5Q60enUE3xkv.WHnQE3KmFdK.jBuNVqCvBI2F6uuCNHN77zTn2byLh0Wm9A!/r

然而这个两个方法看起来方便

但是会隐藏着巨坑,由于这个文件是静态资源,所以当你的浏览器在请求的时候会被当作文件下载,这个请求的返回会被IDM这样的下载软件捕获而拦截。

http://r.photo.store.qq.com/psc?/V51omi8H2ZybVP1W54I94cQfjz0BuScw/45NBuzDIW489QBoVep5mcSxUmTZ9Nyu02gmc4lRzgvwTz40R5M*aTPWerMD6mODJFUY9pnRpqsQ9ozs0VaVIHWQOR3y*8GfW3nOXh6htv1w!/r

你的请求只会得到一个状态为204的返回,或者根本没有任何返回,这将导致你无法获取pdf从而解析加载

http://r.photo.store.qq.com/psc?/V51omi8H2ZybVP1W54I94cQfjz0BuScw/45NBuzDIW489QBoVep5mcc1KiZ7sqaLAzoIHYyXMmGf6O7.ZIKKtUM7DKOpibeiO1MHbsAmB.S55dWq7HmP2PjfL8Pzj8je3ZPPUGJVa2Hg!/r