js实现pdf文件上传预览功能
需求: 上传预览功能, 支持图片和pdf上传预览, 并且是在指定的div里面预览
主要使用的是pdfjs库
pdfjs可以轻松实现点击打开一个新的页面或一个大的dialog在原页面实现预览, 但是不支持(可能是我没找到)在指定的div里面预览
这里要实现的是在指定的div里面预览
-
依赖下载
下载stable(v2.16.105)
解压后在build目录下找到pdf.js和pdf.work.js两个文件, copy到自己的项目
使用了jquery方便dom操作
-
具体实现的功能:pdf上传显示, 上一页, 下一页
-
关键代码
一个上传按钮, 点击时触发文件选择事件
<button onclick="choosePdf()">选择一个pdf文件</button> <input style="display:none" id='chooseFile' type='file' accept="application/pdf"> function choosePdf(){ $("#chooseFile").click() }
具体逻辑是在上传的change事件中实现的
$("#uploadFile").change(function() {...})
注意, 在网上找过很多版本, copy下来之后发现都有问题, 应该是pdfjs版本更新的问题, debugger了一下, 主要是两个地方:
var loadingTask = pdfjsLib.getDocument(this.result) loadingTask.promise.then(function(pdf) {}) // 这里 pdfjsLib.getDocument的参数是一个dataUrl, 直接使用上传的file是不行的 // pdfjsLib.getDocument里面包含一个promise对象, 之前的版本是直接 .then, 现在是.promise.then
var viewport = page.getViewport({scale: scale}) // 这里page.getViewport 的参数是一个对象形式, 之前的版本 可以直接传一个数字, 0.5 , 1,2 , 现在如果直接数字的话, 获取的结果 height和 weight都是 NaN,
具体代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>pdf预览实现</title> <style> #container { width: 600px; height: 800px; margin-top: 5px; position: relative; border: 1px solid #333; } .commonBtn { position: absolute; width: 80px; height: 35px; line-height: 35px; text-align: center; background-color: #409eff; border-radius: 20px; color: #fff; cursor: pointer; } .commonBtn:hover { background-color: #66b1ff; } #pre { top: 20px; left: 20px; } #next { top: 20px; right: 20px; } #total { position: absolute; width: 50px; height: 30px; top: 20px; left: 50%; color: blueviolet; } #uploadBtn { display: inline-block; width: 80px; height: 35px; line-height: 35px; color: #fff; background-color: #67c23a; border-radius: 20px; cursor: pointer; text-align: center; } .forbid-click { background-color: #909399; cursor: not-allowed !important; } .forbid-click:hover { background-color: #909399 !important; } #fileName { color: aqua; margin-left: 20px; } #size { color: aquamarine; margin-left: 20px; } </style> </head> <body> <div id="opera_area"> <span id="uploadBtn">选择文件</span> <span id="fileName"></span> <span id="size"></span> <input type="file" name="" id="uploadFile" accept="application/pdf" style="display: none;"> </div> <div id="container"> <div id="pre" class="commonBtn forbid-click">上一页</div> <div id="next" class="commonBtn forbid-click">下一页</div> <div id="total" style="display: none;"><span id="currentPage"></span>/<span id="totalPage"></span></div> </div> <script src="js/jq.js"></script> <script src="js/pdf.js"></script> <script src="js/pdf.worker.js"></script> <script> var choosenFile = {} var total = 0 var current = 0 var scale = 1 $(function() { $("#uploadBtn").click(function(e) { $("#uploadFile").click() }) $("#pre").click(function(e) { if($("#pre").hasClass('forbid-click')) return var currentCanvas = $('#canvas_' + current) currentCanvas.hide() $('#canvas_' + (current - 1)).show() current -= 1 setPageState() }) $("#next").click(function(e) { if($("#next").hasClass('forbid-click')) return var currentCanvas = $('#canvas_' + current) currentCanvas.hide() $('#canvas_' + (current + 1)).show() current += 1 setPageState() }) function setPageState() { setCurPage() if(current <= 1) { $("#pre").addClass('forbid-click') } else { $("#pre").removeClass('forbid-click') } if(current >= total) { $("#next").addClass('forbid-click') } else { $("#next").removeClass('forbid-click') } } function setCurPage() { $('#currentPage').text(current) $('#totalPage').text(total) } function renderCanvas(pdf, i, canvas) { var outputScale = window.devicePixelRatio || 1 pdf.getPage(i).then(function(page) { var viewport = page.getViewport({scale: scale}) var context = canvas.getContext('2d') canvas.width = Math.floor(viewport.width * outputScale) canvas.height = Math.floor(viewport.height * outputScale) canvas.style.width = Math.floor(viewport.width) + 'px' canvas.style.height = Math.floor(viewport.height) + 'px' var transform = outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0]: null var renderContext = { canvasContext: context, transform: transform, viewport: viewport } if(i != 1) { canvas.style.display = 'none' } page.render(renderContext) }) } $("#uploadFile").change(function(e) { var file = e.target.files[0] if(file.size > 5 * 1024 * 1024) { return alert('上传文件大于5M') } $("#container canvas").remove() $('#total').show() current = 1 choosenFile.fileName = file.name choosenFile.size = (file.size/(1024 * 1024)).toFixed(2) choosenFile.file = file $("#fileName").text(choosenFile.fileName) $("#size").text(choosenFile.size + 'MB') var reader = new FileReader() reader.readAsDataURL(file) reader.onload = function(e) { // getDocument的参数是一个dataUrl var loadingTask = pdfjsLib.getDocument(this.result) loadingTask.promise.then(function(pdf) { if(pdf) { total = pdf.numPages current = 1 setCurPage() setPageState() } for(var i = 1; i <= total; i ++) { var canvas = document.createElement('canvas') canvas.id = 'canvas_' + i $("#container").append(canvas) // 这里封装成一个方法, 不能散装在这里, 因为异步会有问题 renderCanvas(pdf, i, canvas) } }) } }) }) </script> </body> </html>
实现的效果