背景
年前的时候, 开发一个电子杂志项目, 功能需求是通过上传 PDF 文件, 将其转为图片格式, 所以杂志的内容其实就是一张张图片
不过当时技术要求用后端实现, 所以使用的是 PHP 实现该功能. 项目完成后, 寻思着在前端是否也能实现 PDF 转图片的功能. 一番研究后, 果真可行. 以下就分享如何通过前端 JS 将 PDF 文件转为图片格式, 并且支持翻页预览, 以及图片打包下载
效果预览
所需工具
- PDF.JS(负责 API 解析, 可将 PDF 文件渲染成 canvas 实现预览)
- PDF.worker.JS(负责核心解析)
- jszip.JS(将图片打包成生成. zip 文件)
- Filesaver.JS(保存下载 zip 文件)
工具下载
一, PDF.JS 及 PDF.worker.JS 下载地址:
http://mozilla.github.io/pdf.js/getting_started/#download
1. 选择稳定版下载
2. 解压后将 bulid 中的 PDF.JS 及 PDF.worker.JS 拷贝到项目中
二, jszip.JS 及 Filesaver.JS 下载地址:
https://stuk.github.io/jszip/
1. 点击 download.JSZip
2. 解压后将 dist 文件夹下的 jszip.JS 文件以及 vendor 文件夹下的 FileSaver.JS 文件拷贝到项目中
至此, 所需工具已齐全. 以下直接附上项目完整代码 (代码可直接复制使用, 查看效果. 对应的文件需自行下载引入)
源代码: 嫌麻烦的小伙伴可以直接在公众号后回复: PDF 转图片
代码实现
- <!DOCTYPE html>
- <HTML>
- <head>
- <meta charset="utf-8" />
- <title>
- PDF 文件转图片
- </title>
- <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
- </script>
- <script type="text/javascript" src="js/pdf.js">
- </script>
- <script type="text/javascript" src="js/pdf.worker.js">
- </script>
- <script type="text/javascript" src="js/jszip.js">
- </script>
- <script type="text/javascript" src="js/FileSaver.js">
- </script>
- <style type="text/CSS">
- button { width: 120px; height: 30px; background: none; border: 1px solid
- #b1afaf; border-radius: 5px; font-size: 12px; font-weight: 1000; color:
- #384240; cursor: pointer; outline: none; margin: 0 0.5% } button:hover
- { background: #ccc; } #container { width: 600px; height: 780px; margin-top:
- 1%; border-radius: 2px; border: 2px solid #a29b9b; } .pdfInfos { margin:
- 0 2%; }
- </style>
- </head>
- <body>
- <div style="margin-top:1%">
- <button id="prevpage">
- 上一页
- </button>
- <button id="nextpage">
- 下一页
- </button>
- <button id="exportImg">
- 导出图片
- </button>
- <button onclick="choosePdf()">
- 选择一个 PDF 文件
- </button>
- <input style="display:none" id='chooseFile' type='file' accept="application/pdf">
- </div>
- <div style="margin-top:1%">
- <span class="pdfInfos">
- 页码:
- <span id="currentPages">
- </span>
- <span id="totalPages">
- </span>
- </span>
- <span class="pdfInfos">
- 文件名:
- <span id="fileName">
- </span>
- </span>
- <span class="pdfInfos">
- 文件大小:
- <span id="fileSize">
- </span>
- </span>
- </div>
- <div style="position: relative;">
- <div id="container">
- </div>
- <img id="imgloading" style="position: absolute;top: 20%;left: 2%;display:none"
- src="loading.gif">
- </div>
- </body>
- <script>
- var currentPages, totalPages // 声明一个当前页码及总页数变量
- var scale = 2; // 设置缩放比例, 越大生成图片越清晰
- $('#chooseFile').change(function() {
- var pdfFilePath = $('#chooseFile').val();
- if (pdfFilePath) {
- $("#imgloading").CSS('display', 'block');
- $("#container").empty(); // 清空上一 PDF 文件展示图
- currentPages = 1; // 重置当前页数
- totalPages = 0; // 重置总页数
- var filesdata = $('#chooseFile')[0].files; //jQuery 获取到文件 返回属性的值
- var fileSize = filesdata[0].size; // 文件大小
- var mb;
- if (fileSize) {
- mb = fileSize / 1048576;
- if (mb > 10) {
- alert("文件大小不能 > 10M");
- return;
- }
- }
- $("#fileName").text(filesdata[0].name);
- $("#fileSize").text(mb.toFixed(2) + "Mb");
- var reader = new FileReader();
- reader.readAsDataURL(filesdata[0]); // 将文件读取为 DataURL
- reader.onload = function(e) { // 文件读取成功完成时触发
- pdfjsLib.getDocument(this.result).then(function(PDF) { // 调用 PDF.JS 获取文件
- if (PDF) {
- totalPages = PDF.numPages; // 获取 PDF 文件总页数
- $("#currentPages").text("1/");
- $("#totalPages").text(totalPages);
- // 遍历动态创建 canvas
- for (var i = 1; i <= totalPages; i++) {
- var canvas = document.createElement('canvas');
- canvas.id = "pageNum" + i;
- $("#container").append(canvas);
- var context = canvas.getContext('2d');
- renderImg(PDF, i, context);
- }
- }
- });
- };
- }
- });
- // 渲染生成图片
- function renderImg(pdfFile, pageNumber, canvasContext) {
- pdfFile.getPage(pageNumber).then(function(page) { // 逐页解析 PDF
- var viewport = page.getViewport(scale); // 页面缩放比例
- var newcanvas = canvasContext.canvas;
- // 设置 canvas 真实宽高
- newcanvas.width = viewport.width;
- newcanvas.height = viewport.height;
- // 设置 canvas 在浏览中宽高
- newcanvas.style.width = "100%";
- newcanvas.style.height = "100%";
- // 默认显示第一页, 其他页隐藏
- if (pageNumber != 1) {
- newcanvas.style.display = "none";
- }
- var renderContext = {
- canvasContext: canvasContext,
- viewport: viewport
- };
- page.render(renderContext); // 渲染生成
- });
- $("#imgloading").CSS('display', 'none');
- return;
- };
- // 上一页
- $("#prevpage").click(function() {
- if (!currentPages || currentPages <= 1) {
- return;
- }
- nowpage = currentPages;
- currentPages--;
- $("#currentPages").text(currentPages + "/");
- var prevcanvas = document.getElementById("pageNum" + currentPages);
- var currentcanvas = document.getElementById("pageNum" + nowpage);
- currentcanvas.style.display = "none";
- prevcanvas.style.display = "block";
- })
- // 下一页
- $("#nextpage").click(function() {
- if (!currentPages || currentPages >= totalPages) {
- return;
- }
- nowpage = currentPages;
- currentPages++;
- $("#currentPages").text(currentPages + "/");
- var nextcanvas = document.getElementById("pageNum" + currentPages);
- var currentcanvas = document.getElementById("pageNum" + nowpage);
- currentcanvas.style.display = "none";
- nextcanvas.style.display = "block";
- })
- // 导出图片
- $("#exportImg").click(function() {
- if (!$('#chooseFile').val()) {
- alert('请先上传 pdf 文件') return false;
- }
- $("#imgloading").CSS('display', 'block');
- var zip = new JSZip(); // 创建一个 JSZip 实例
- var images = zip.folder("images"); // 创建一个文件夹用来存放图片
- // 遍历 canvas, 将其生成图片放进文件夹 images 中
- $("canvas").each(function(index, ele) {
- var canvas = document.getElementById("pageNum" + (index + 1));
- // 将图片放进文件夹 images 中
- // 参数 1 为图片名称, 参数 2 为图片数据 (格式为 base64, 需去除 base64 前缀 data:image/PNG;base64)
- images.file("photo-" + (index + 1) + ".png", splitBase64(canvas.toDataURL("image/png", 1.0)), {
- base64: true
- });
- })
- // 打包下载
- zip.generateAsync({
- type: "blob"
- }).then(function(content) {
- saveAs(content, "picture.zip"); //saveAs 依赖的 JS 文件是 FileSaver.JS
- $("#imgloading").CSS('display', 'none');
- });
- });
- // 截取 base64 前缀
- function splitBase64(dataurl) {
- var arr = dataurl.split(',') return arr[1]
- }
- function choosePdf() {
- $("#chooseFile").click()
- }
- </script>
- </HTML>
项目实现原理分析
首先利用 PDF.JS 将上传的 PDF 文件转化成 canvas
然后使用 jszip.JS 将 canvas 打包图片生成. zip 文件
最后使用 Filesaver.JS 将 zip 文件保存下载
项目注意要点
由于 PDF 文件是通过上传的, 因此需要通过 JS 的 FileReader() 对象将其读取为 DataURL,PDF.JS 文件才可读取渲染
JSZip 对象的. file() 函数中第二个参数传入的是 base64 格式图片, 但是要去掉 base64 前缀标识
最后
觉得文章不错的, 请点个赞哇!
来源: http://www.jianshu.com/p/07943cbf2ecf