上一个章节,简要说了以下分片下载的几个特性。今天主要用示例说明一下pdf.js分片下载。

服务器环境:
php7.2
nginx 1.14
ubuntu 18.04
测试浏览器:谷歌浏览器 70.0.3538.110(

第一个场景,直接使用pdf 文件
1.1 代码如下:注意路径使用的是pdf 文件的物理路径

$filePath = ‘…/doc/big.pdf’;
这里是举例,这样作有一个明显的缺点,就是容易被盗链
getDocument 方法中的 rangeChunkSize 参数,就是设置分块大小,默认是64k,可以修改这个数字,来改变
这个例子使用的 1664k ,1m 左右来分片,方便测试。您可以根据具体情况,来调整
PDFJS.getDocument({url:url,rangeChunkSize:6553616,disableAutoFetch:0}).

  1. <html>
  2. <head><title>pdf.js展示1,上一页,下一页</title></head>
  3. <h1>PDF.js Previous/Next example</h1>
  4. <div>
  5. <button id="prev">Previous</button>
  6. <button id="next">Next</button>     <span>Page: <span id="page_num"></span> / <span
  7. id="page_count"></span></span></div>
  8. <canvas id="the-canvas"></canvas>
  9. <script src="../js/pdfjs/pdf.js"></script>
  10. <script src="../js/pdfjs/pdf.worker.js"></script>
  11. <script>
  12. var url = '../doc/big.pdf';
  13.  
  14. var pdfDoc = null,
  15. pageNum = 1,
  16. pageRendering = false,
  17. pageNumPending = null,
  18. scale = 0.8,
  19. canvas = document.getElementById('the-canvas'),
  20. ctx = canvas.getContext('2d');
  21.  
  22. /**
  23. * Get page info from document, resize canvas accordingly, and render page.
  24. * @param num Page number.
  25. */
  26. function renderPage(num) {
  27. pageRendering = true;
  28. // Using promise to fetch the page
  29. pdfDoc.getPage(num).then(function (page) {
  30. var viewport = page.getViewport(scale);
  31. canvas.height = viewport.height;
  32. canvas.width = viewport.width;
  33.  
  34. // Render PDF page into canvas context
  35. var renderContext = {
  36. canvasContext: ctx,
  37. viewport: viewport
  38. };
  39. var renderTask = page.render(renderContext);
  40.  
  41. // Wait for rendering to finish
  42. renderTask.promise.then(function () {
  43. pageRendering = false;
  44. if (pageNumPending !== null) {
  45. // New page rendering is pending
  46. renderPage(pageNumPending);
  47. pageNumPending = null;
  48. }
  49. });
  50. });
  51.  
  52. // Update page counters
  53. document.getElementById('page_num').textContent = num;
  54. }
  55.  
  56. /**
  57. * If another page rendering in progress, waits until the rendering is
  58. * finised. Otherwise, executes rendering immediately.
  59. */
  60. function queueRenderPage(num) {
  61. if (pageRendering) {
  62. pageNumPending = num;
  63. } else {
  64. renderPage(num);
  65. }
  66. }
  67.  
  68. /**
  69. * Displays previous page.
  70. */
  71. function onPrevPage() {
  72. if (pageNum <= 1) {
  73. return;
  74. }
  75. pageNum--;
  76. queueRenderPage(pageNum);
  77. }
  78.  
  79. document.getElementById('prev').addEventListener('click', onPrevPage);
  80.  
  81. /**
  82. * Displays next page.
  83. */
  84. function onNextPage() {
  85. if (pageNum >= pdfDoc.numPages) {
  86. return;
  87. }
  88. pageNum++;
  89. queueRenderPage(pageNum);
  90. }
  91.  
  92. document.getElementById('next').addEventListener('click', onNextPage);
  93.  
  94. /**
  95. * Asynchronously downloads PDF.
  96. */
  97. PDFJS.getDocument({url:url,rangeChunkSize:65536*16,disableAutoFetch:0}).then(function(pdfDoc_) {
  98. pdfDoc = pdfDoc_;
  99. document.getElementById('page_count').textContent = pdfDoc.numPages;
  100.  
  101. // Initial/first page rendering
  102. renderPage(pageNum);
  103. });
  104. </script>
  105. </html>

  

1.2今天第一加载:发现没有出现分片效果。如果您也遇到这种情况,不要着急,很大程度是因为浏览器缓存

1.3 在浏览器中,安Ctrl+alt+delte 键,清除缓存


1.4 清除缓存后,再次刷新页面,发现分片下载功能出现了。

  1. 后台代码
  2.  
  3. <?php
  4. $filePath = '../doc/big.pdf';
  5.  
  6. //普通的方式处理包装pdf文件
  7. download_file($filePath);
  8.  
  9. function download_file($file, $fname = 'chunk.pdf')
  10. {
  11. header("Content-Type: application/octet-stream");
  12. header("Content-Disposition: attachment;filename=$fname");
  13.  
  14. echo(file_get_contents($file));
  15. }

  前台js 调用代码

  1. 。。。。。
  2. var url = 'download.php';
  3.  
  4. var pdfDoc = null,
  5. pageNum = 1,
  6. pageRendering = false,
  7. pageNumPending = null,
  8. scale = 0.8,
  9. canvas = document.getElementById('the-canvas'),
  10. ctx = canvas.getContext('2d');
  11.  
  12. 。。。。

  

2.2 经过清理缓存,发现无法达到分片的效果。

初步总结如下,常规的附件处理方式,会影响分片下载的效果

场景3:使用php 结合httprange,实现分片的效果

3.1 这里是从网上搜集到的分片下载php 函数

代码的核心是,增加head 头,开启分片 Header("Accept-Ranges: bytes"); 至于 Http range 如何计算,就比较繁琐了,这里就不详细介绍了。有兴趣的可以去百度

  1. <?php
  2. $filePath = '../doc/big.pdf';
  3.  
  4. //分片下载
  5. chunk_download_file($filePath);
  6.  
  7. /**
  8. * 分篇下载的汉书
  9. *
  10. * @param $file
  11. * @param $fname
  12. */
  13. function chunk_download_file($file, $fname = 'chunk.pdf')
  14. {
  15. $fhandle = fopen($file, 'rb');//文件句柄
  16. $fsize = filesize($file);//文件大小
  17.  
  18. //断点续传和整个文件下载的判断,支持多段下载
  19. if (!empty($_SERVER['HTTP_RANGE'])) {
  20. $range = str_replace("=", "-", $_SERVER['HTTP_RANGE']);
  21. $match = explode("-", $range);
  22. $start = $match[1];
  23. $end = !empty($match[2]) ? $match[2] : $fsize - 1;
  24. } else {
  25. $start = 0;
  26. $end = $fsize - 1;
  27. }
  28.  
  29. if (($end - $start) < ($fsize - 1)) {
  30. fseek($fhandle, $start);
  31. header("HTTP/1.1 206 Partial Content");
  32. header("Content-Length: " . ($end - $start + 1));
  33. header("Content-Range: bytes " . $start . "-" . $end . "/" . $fsize);
  34. } else {
  35. header("HTTP/1.1 200 OK");
  36. header("Content-Length: $fsize");
  37. Header("Accept-Ranges: bytes");
  38. header("Content-Range: bytes " . $start . "-" . $end . "/" . $fsize);
  39. }
  40.  
  41. header("Content-Type: application/octet-stream");
  42. header("Content-Disposition: attachment;filename=$fname");
  43.  
  44. if (!feof($fhandle)) {
  45. set_time_limit(0);
  46. $buffer = fread($fhandle, $end - $start + 1);
  47. echo $buffer;
  48. flush();
  49. ob_flush();
  50. }
  51. }

  

demo 下载路径:
https://download.csdn.net/download/niedewang/10804164

3.2 清理调浏览器缓存,发现这种方式可以达到分片下载的效果

经过测试,谷歌浏览器支持的很好,如上图所示,截图就是使用的谷歌浏览器。
但是firefox 在这种场景下,分片效果不理想。具体原因未知

简要的总结
1:前期承诺的demo 放出来了,blog貌似会清理连接地址,不知道是否会删除
2:使用pdf 真实文件路径,分片兼容性最好。但是地址容易泄漏
3:如果使用php 处理,一般的处理程序,不能达到分片效果。需要结合http range特性,但是不知道什么原因,firefox测试下来,效果不好。谷歌浏览器支持的较好,好消息是谷歌浏览器现在占用量是最大的。
4:后面有时间了,会介绍以下使用 x-sendfile 的方式处理附件,无论性能还是兼容性都比php 处理要好
---------------------
作者:只看远方
来源:CSDN
原文:https://blog.csdn.net/niedewang/article/details/84576969
版权声明:本文为博主原创文章,转载请附上博文链接!

PDF.js 分片下载的介绍2:分片下载demo的更多相关文章

  1. Mongodb主从复制/ 副本集/分片集群介绍

    前面的文章介绍了Mongodb的安装使用,在 MongoDB 中,有两种数据冗余方式,一种 是 Master-Slave 模式(主从复制),一种是 Replica Sets 模式(副本集). Mong ...

  2. 利用PDF.JS插件解决了本地pdf文件在线浏览问题(根据需要隐藏下载功能,只保留打印功能)

    我是在IE11和谷歌上做的测试,都可以显示,把做出的东西记录下来,方便大家还有自己学习! 可以在IIS7服务器上也可以下载Tomcat来做服务器 Tomcat下载地址   http://pan.bai ...

  3. Mongo 整体架构介绍(1)-------分片集群

    摘要 在mongo初识文中介绍了mongo与cassandra的主要区别,以及mongo物理部署架构图.本文接着上一篇的mongo 架构图,来继续讲分片集群. 分片介绍 shard key mongo ...

  4. 【七】MongoDB管理之分片集群介绍

    分片是横跨多台主机存储数据记录的过程,它是MongoDB针对日益增长的数据需求而采用的解决方案.随着数据的快速增长,单台服务器已经无法满足读写高吞吐量的需求.分片通过水平扩展的方式解决了这个问题.通过 ...

  5. 第二章·Elasticsearch内部分片及分片处理机制介绍

    一.副本分片介绍 什么是副本分片? 副本分片的主要目的就是为了故障转移,如果持有主分片的节点挂掉了,一个副本分片就会晋升为主分片的角色. 在索引写入时,副本分片做着与主分片相同的工作.新文档首先被索引 ...

  6. 预览下载的pdf的——pdf.js

    1.需要到官网下载源码:https://mozilla.github.io/pdf.js/ 2. function(){ let url='./demo1.pdf'; window.location. ...

  7. Vue.js +pdf.js 处理响应pdf文件流数据,前端转图片预览不可下载

    使用场景及原因 实际业务中,一些说明书或协议仅支持用户在线预览,为避免用户自行下载,并进行修改,引发纠纷,特将文件已文件流的形式,传给前端并转为图片显示,此时可能会有人问,为什么不直接在后端转图片,前 ...

  8. 小谢第7问:js前端如何实现大文件分片上传、上传进度、终止上传以及删除服务器文件?

    文件上传一般有两种方式:文件流上传和base64方式上传,毫无疑问,当进行大文件上传时候,转为base64是不现实的,因此用formData方式结合文件流,直接上传到服务器 本文主要结合vue的来讲解 ...

  9. pdf.js pdfdom.js使用(转)

    开篇语: 最近工作需要做一个借款合同,公司以前的合同都是通过app端下载,然后通过本地打开pdf文件,而喜欢创新的我,心想着为什么不能在线H5预览,正是这个想法,说干就干,实践过程总是艰难的,折腾了3 ...

随机推荐

  1. AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-SoundHound-Inc-Programming-Contest-2018-E.html 题目 ...

  2. Ubuntu18.04上安装java

    安装java8 sudo add-apt-repository ppa:webupd8team/javasudo apt-get updatesudo apt-get install oracle-j ...

  3. P2279 [HNOI2003]消防局的设立 贪心or树形dp

    题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...

  4. HUE的自动化安装部署

    HUE=Hadoop User Experience(Hadoop用户体验),直白来说就一个开源的Apache Hadoop UI系统,由Cloudera Desktop演化而来,最后Cloudera ...

  5. JavaSE| 面向对象的三大特征

    1.面向对象的基本特征之一:封装Encapsulation 目的:隐藏实现细节,让使用者方便,让代码更安全 将对象的属性和行为封装起来,其载体就是类.类通常对客户隐藏其实现细节,这就是封装的思想. 封 ...

  6. utf-8和utf8的区别

    utf-8 和 utf8 的区别与使用: "UTF-8" 是标准写法,php 在 Windows 系统里的英文不区分大小写,所以也可以写成 "utf-8".&q ...

  7. Spring Security(15)——权限鉴定结构 RoleVoter

    http://www.cnblogs.com/fenglan/p/5913432.html

  8. spring cloud 详解

    https://www.cnblogs.com/qdhxhz/p/9601170.html SpringCloud(8)---zuul权限校验.接口限流 https://blog.csdn.net/c ...

  9. notepad++ 去空行

    Press Ctrl+H (Replace) Select Extended from SearchMode Put \r\n\r\n in Find What Put \r\n in Replace ...

  10. asp.net core Session的测试使用心得及注意事项

    sp.net-core中Session是以中间件的形式注册使用的.不比asp.net中的使用,直接使用Session就行. 首先在.net-core框架中注入Session中间件,首先在Configu ...