乐趣区

关于前端:JS逐页转pdf文件为图片格式

背景

年前的时候,开发一个电子杂志我的项目,性能需要是通过上传 pdf 文件,将其转为图片格式,所以杂志的内容其实就是一张张图片

不过过后技术要求用后端实现,所以应用的是 PHP 实现该性能。我的项目实现后,寻思着在前端是否也能实现 pdf 转图片的性能。一番钻研后,果然可行。以下就分享如何通过前端 js 将 pdf 文件转为图片格式, 并且反对翻页预览、以及图片打包下载

成果预览

所需工具

1.pdf.js(负责 API 解析,可将 pdf 文件渲染成 canvas 实现预览)
2.pdf.worker.js(负责外围解析)
3.jszip.js(将图片打包成生成.zip 文件)
4.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 文件拷贝到我的项目中

至此,所需工具已齐全。以下间接附上我的项目残缺代码(代码可间接复制应用,查看成果。对应的文件需自行下载引入)

源代码:嫌麻烦的小伙伴能够间接在公众号【GitWeb】回复: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>

我的项目实现原理剖析

1. 首先利用 pdf.js 将上传的 pdf 文件转化成 canvas
2. 而后应用 jszip.js 将 canvas 打包图片生成.zip 文件
3. 最初应用 Filesaver.js 将 zip 文件保留下载

我的项目留神要点

1. 因为 pdf 文件是通过上传的,因而须要通过 js 的 FileReader() 对象将其读取为 DataURL,pdf.js 文件才可读取渲染

2.JSZip 对象的.file() 函数中第二个参数传入的是 base64 格局图片,然而要去掉 base64 前缀标识

退出移动版