前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PDF.js 分片下载的介绍2:分片下载demo

PDF.js 分片下载的介绍2:分片下载demo

作者头像
庞小明
发布2019-05-25 18:01:52
12.2K0
发布2019-05-25 18:01:52
举报
文章被收录于专栏:pangguomingpangguoming

服务器环境: 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}).

代码语言:javascript
复制
<html>
    <head><title>pdf.js展示1,上一页,下一页</title></head>
    <h1>PDF.js Previous/Next example</h1>
    <div>
        <button id="prev">Previous</button>
        <button id="next">Next</button>     <span>Page: <span id="page_num"></span> / <span
            id="page_count"></span></span></div>
    <canvas id="the-canvas"></canvas>
    <script src="../js/pdfjs/pdf.js"></script>
    <script src="../js/pdfjs/pdf.worker.js"></script>
    <script>
        var url = '../doc/big.pdf';
     
    
        var pdfDoc = null,
            pageNum = 1,
            pageRendering = false,
            pageNumPending = null,
            scale = 0.8,
            canvas = document.getElementById('the-canvas'),
            ctx = canvas.getContext('2d');
    
        /**
         * Get page info from document, resize canvas accordingly, and render page.
         * @param num Page number.
         */
        function renderPage(num) {
            pageRendering = true;
            // Using promise to fetch the page
            pdfDoc.getPage(num).then(function (page) {
                var viewport = page.getViewport(scale);
                canvas.height = viewport.height;
                canvas.width = viewport.width;
    
                // Render PDF page into canvas context
                var renderContext = {
                    canvasContext: ctx,
                    viewport: viewport
                };
                var renderTask = page.render(renderContext);
    
                // Wait for rendering to finish
                renderTask.promise.then(function () {
                    pageRendering = false;
                    if (pageNumPending !== null) {
                        // New page rendering is pending
                        renderPage(pageNumPending);
                        pageNumPending = null;
                    }
                });
            });
    
            // Update page counters
            document.getElementById('page_num').textContent = num;
        }
    
        /**
         * If another page rendering in progress, waits until the rendering is
         * finised. Otherwise, executes rendering immediately.
         */
        function queueRenderPage(num) {
            if (pageRendering) {
                pageNumPending = num;
            } else {
                renderPage(num);
            }
        }
    
        /**
         * Displays previous page.
         */
        function onPrevPage() {
            if (pageNum <= 1) {
                return;
            }
            pageNum--;
            queueRenderPage(pageNum);
        }
    
        document.getElementById('prev').addEventListener('click', onPrevPage);
    
        /**
         * Displays next page.
         */
        function onNextPage() {
            if (pageNum >= pdfDoc.numPages) {
                return;
            }
            pageNum++;
            queueRenderPage(pageNum);
        }
    
        document.getElementById('next').addEventListener('click', onNextPage);
    
        /**
         * Asynchronously downloads PDF.
         */
        PDFJS.getDocument({url:url,rangeChunkSize:65536*16,disableAutoFetch:0}).then(function(pdfDoc_) {
            pdfDoc = pdfDoc_;
            document.getElementById('page_count').textContent = pdfDoc.numPages;
    
            // Initial/first page rendering
            renderPage(pageNum);
        });
    </script>
    </html>

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

在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述

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

代码语言:javascript
复制
后台代码

 <?php
$filePath = '../doc/big.pdf';

//普通的方式处理包装pdf文件 
download_file($filePath);

function download_file($file, $fname = 'chunk.pdf')
{
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment;filename=$fname");

    echo(file_get_contents($file));
}

  前台js 调用代码

代码语言:javascript
复制
  。。。。。
    var url = 'download.php';

    var pdfDoc = null,
        pageNum = 1,
        pageRendering = false,
        pageNumPending = null,
        scale = 0.8,
        canvas = document.getElementById('the-canvas'),
        ctx = canvas.getContext('2d');

。。。。

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

在这里插入图片描述
在这里插入图片描述

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

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

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

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

代码语言:javascript
复制
<?php
$filePath = '../doc/big.pdf';

//分片下载
chunk_download_file($filePath);


/**
 * 分篇下载的汉书
 *
 * @param $file
 * @param $fname
 */
function chunk_download_file($file, $fname = 'chunk.pdf')
{
    $fhandle = fopen($file, 'rb');//文件句柄
    $fsize = filesize($file);//文件大小

    //断点续传和整个文件下载的判断,支持多段下载
    if (!empty($_SERVER['HTTP_RANGE'])) {
        $range = str_replace("=", "-", $_SERVER['HTTP_RANGE']);
        $match = explode("-", $range);
        $start = $match[1];
        $end = !empty($match[2]) ? $match[2] : $fsize - 1;
    } else {
        $start = 0;
        $end = $fsize - 1;
    }

    if (($end - $start) < ($fsize - 1)) {
        fseek($fhandle, $start);
        header("HTTP/1.1 206 Partial Content");
        header("Content-Length: " . ($end - $start + 1));
        header("Content-Range: bytes " . $start . "-" . $end . "/" . $fsize);
    } else {
        header("HTTP/1.1 200 OK");
        header("Content-Length: $fsize");
        Header("Accept-Ranges: bytes");
        header("Content-Range: bytes " . $start . "-" . $end . "/" . $fsize);
    }

    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment;filename=$fname");

    if (!feof($fhandle)) {
        set_time_limit(0);
        $buffer = fread($fhandle, $end - $start + 1);
        echo $buffer;
        flush();
        ob_flush();
    }
}

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

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

简要的总结 1:前期承诺的demo 放出来了,blog貌似会清理连接地址,不知道是否会删除 2:使用pdf 真实文件路径,分片兼容性最好。但是地址容易泄漏 3:如果使用php 处理,一般的处理程序,不能达到分片效果。需要结合http range特性,但是不知道什么原因,firefox测试下来,效果不好。谷歌浏览器支持的较好,好消息是谷歌浏览器现在占用量是最大的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-01-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景3:使用php 结合httprange,实现分片的效果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档