pdf.js 是一块将pdf文件进行再加工然后页面展示的小插件,可以实现自定义水印、编辑下载打印权限等功能。
开发过程遇到很多问题,可以直接看最后一部分。
show time
1、下载 http://mozilla.github.io/pdf.js/getting_started/#download

下载后的文件这样

附一个下载地址 https://files.cnblogs.com/files/xiufengd/pdfjs-2.16.105-dist.zip?t=1667295509
2、服务端提供二进制流的文件 代码如下
@GetMapping("/show")
@ResponseBody
public void showReportPDF(String id, @RequestHeader("Referer") String referer){
HttpServletResponse response = ApplicationContextUtil.getHttpServletResponse();
String Host = profiles.equals("test")?
"testurl"
:
profiles.equals("prod")?
"produrl"
:
"";
// 来源检测,文件一般都是比较重要的 所以想要检测同源
if(referer.indexOf(Host)==-1&&referer.indexOf("localhost:8080")==-1){
throw new BusinessException(GsonUtil.toJson(new Message(MessageCode.NOAUTH.getCode(),"无权限")));
}
try {
// reportService.getReportInputStream 是返回一个InputStream类型的方法 用于从数据库或者其他地方获取文件的InputStream流
BufferedInputStream br = new BufferedInputStream(reportService.getReportInputStream(id));
byte[] buf = new byte[1024];
int len = 0;
response.reset(); // 非常重要
response.setContentType("application/pdf");
// 处理直接请求跨域问题 一定注意是用addHeader 而不是setHeader
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.addHeader("Content-Disposition",
"inline; filename=" + java.net.URLEncoder.encode(id+".pdf", "UTF-8"));
// 将文件流输出到response中
OutputStream out = response.getOutputStream();
while ((len = br.read(buf)) != -1) {
out.write(buf, 0, len);
out.flush();
}
br.close();
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
3、前端 注意 调用要用原生的ajax 否则会造成展示的文件页面正确但是内容为空的情况!!!
var xhr = new XMLHttpRequest(); xhr.open( "get","http://localhost:8000/report/show?id=22222", true );
// 注意类型是blob xhr.responseType = "blob";
// 如果有权限校验 记得添加header xhr.setRequestHeader("token", "222222"); xhr.onload = function() {
// 将返回的response构建URL 然后传输到插件里 const url = window.URL.createObjectURL(this.response); window.open("/pdf/web/viewer.html?file=" + url);
//展示2秒钟后 将链接失效 方式连接泄露 setTimeout(() => window.URL.revokeObjectURL(url), 2000); }; xhr.send();
4、个性化设置
如果想禁用下载、打印、复制之类的工作,想要编辑 pdf\web\viewer.html 这个文件 在header里添加以下代码
<script>
// 禁止右键、区域选择和复制
oncontextmenu="window.event.returnValue=false"
oncopy ="window.event.returnValue=false"
ondragstart ="window.event.returnValue=false"
onselectstart="window.event.returnValue=false"
// 禁止键盘操作
window.onkeydown = window.onkeyup = window.onkeypress = function (event) {
event.preventDefault(); // 阻止默认事件行为
window.event.returnValue = false;
}
// 屏蔽功能按钮
function onBodyLoad(){
var appConfig = PDFViewerApplication.appConfig;
appConfig.toolbar.viewBookmark.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.viewBookmarkButton.setAttribute('hidden', 'true');
appConfig.toolbar.openFile.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.openFileButton.setAttribute('hidden', 'true');
appConfig.toolbar.download.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.downloadButton.setAttribute('hidden', 'true');
appConfig.toolbar.print.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.printButton.setAttribute('hidden', 'true');
}
// 禁止右键下载,打印
function stop(){
return false;
}
document.oncontextmenu = stop;
</script>
5、问题点
5.1 打开新页面后一片空白,但是接口返回正常
不能用axios来调用,要用最原始的ajax来调用
5.2 页面正常打开,表格展示正常,但是文字不显示
字体没有正确加载 ,将viewer.js的cMapUrl内容"../web/cmaps/"修改为“https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/cmaps/”

5.3 工具栏图标没有正常加载,单独访问提示跨域
pdf/web/images下的svg图片加载失败,转换成png图片并修改viewer.css里的引用即可
浙公网安备 33010602011771号