天天看點

PDF網頁線上預覽

C# ASP.NET環境下,利用PDF.JS實作。其實99%都是頁面JavaScipt程式,C#僅用于從背景擷取PDF檔案路徑。

程式目的适用于,在如IE等無法線上預覽PDF檔案,而是直接彈出下載下傳連結的浏覽器中線上預覽檔案的情況。

使用的庫如下;

<script type="text/javascript" src="js/pdf/js/jszip.min.js"></script>
<script type="text/javascript" src="js/pdf/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="js/pdf/js/pdf.js"></script>
<script type="text/javascript" src="js/pdf/js/pdf.worker.js"></script>
           

可在Github的PDF.JS項目中擷取。大多使用辦法都是利用項目中的viewer.html實作線上預覽。但本文直接使用頁面畫闆标簽<canvas>實作。

代碼如下:

網頁HTML

<td id="pdfIframe" style="width:100%">                            
    <label id="pdfurl" style="display:none" ><%=pdfurl %></label>
    <canvas id="the-canvas"></canvas>
    <div style="text-align: center"> 
        <button id="prev" style="width:60px">上一頁</button> 
        <button id="next" style="width:60px">下一頁</button> 
        <span>頁數: <span id="page_num"></span> / <span id="page_count"></span></span> 
    </div> 
</td>
           

JavaScript

<script type="text/javascript">

    var url = "file/" + document.getElementById('pdfurl').innerText;

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

    var height = window.innerHeight;
    var myDiv = document.getElementById("pdfIframe");
    myDiv.style.height = (height - 20) + "px";

    function renderPage(num) {
        pageRendering = true;
        pdfDoc.getPage(num).then(function (page) {           
                            
            var viewport = page.getViewport(scale);
            canvas.height = viewport.height;
            canvas.width = viewport.width;

            var renderContext = {
                canvasContext: ctx,
                viewport: viewport
            };
            var renderTask = page.render(renderContext);

            renderTask.promise.then(function () {
                pageRendering = false;
                if (pageNumPending !== null) {
                    // New page rendering is pending 
                    renderPage(pageNumPending);
                    pageNumPending = null;
                }
            });
        });

        document.getElementById('page_num').textContent = pageNum;
    }

    function queueRenderPage(num) {
        if (pageRendering) {
            pageNumPending = num;
        } else {
            renderPage(num);
        }
    }

    function onPrevPage() {
        if (pageNum <= 1) {
            return;
        }
        pageNum--;
        queueRenderPage(pageNum);
    }

    document.getElementById('prev').addEventListener('click', onPrevPage);

    function onNextPage() {
        if (pageNum >= pdfDoc.numPages) {
            return;
        }
        pageNum++;
        ueueRenderPage(pageNum);
    }

    document.getElementById('next').addEventListener('click', onNextPage);

    PDFJS.getDocument(url).then(function (pdfDoc_) {
        pdfDoc = pdfDoc_;
        document.getElementById('page_count').textContent = pdfDoc.numPages;

        pdfDoc.getPage(1).then(function (page) {
            var viewport = page.getViewport(scale);
            scale = (myDiv.clientWidth / viewport.width).toFixed(1);

        });

        renderPage(pageNum);
    });

</script>
           

通過以上程式,即可實作PDF在頁面上,已畫闆形式顯示,每次展示一頁,翻頁檢視。

在原程式上,增加了自動擷取畫闆高度,根據頁面寬度,自動調整PDF縮放規模的處理。

曾經意圖将PDF自動轉化為PNG圖檔格式存儲,便于調用。也是使用PDF.JS實作。

具體方法是将頁面畫闆canvas中的資料,通過Ajax傳送到.cs檔案中進行處理。但實作過程中遇到的問題是,前端向後端發送資料的速度 非常 非常 非常 緩慢,僅一頁pdf就要等4,5分鐘,還有極大可能完全卡死。偶爾完成的情況下觀察,圖檔也就20多K。

不知道這種情況是否正常,Ajax就無法進行此類規模資料的傳送。還是我的代碼出現了一些問題。

頁面代碼如下:

// PDFJS.disableStream = true;
    $("#export").attr("disabled", "disabled"); //禁用導出圖檔按鈕
    var pdfFile;
    $('#pdf').change(function() {
        var pdfFileURL = $('#pdf').val();
        if(pdfFileURL) {
            $("#imgDiv").empty();//清空上一PDF檔案展示圖
            var files = $('#pdf').prop('files'); //擷取到檔案
            var fileSize = files[0].size;
            var mb;

            if(fileSize) {
                mb = fileSize / 1048576;
                if(mb > 10) {
                    alert("檔案大小不能>10M");
                    return;
                }
            }


            $("#export").removeAttr("disabled", "disabled");
            $("#pdfName").text(files[0].name).attr("title",files[0].name);
            $("#sizeText").text(mb.toFixed(2) + "Mb");

            /*pdf.js無法直接打開本地檔案,是以利用FileReader轉換*/
            var reader = new FileReader();
            reader.readAsArrayBuffer(files[0]);
            reader.onload = function(e) {
                var myData = new Uint8Array(e.target.result)
                var docInitParams = {
                    data: myData
                };
                var typedarray = new Uint8Array(this.result);
                PDFJS.getDocument(typedarray).then(function(pdf) { //PDF轉換為canvas
                    $("#imgDiv").css("border", "0"); //清除文本、邊框
                    if(pdf) {
                        var pageNum = pdf.numPages;
                        $("#pagesText").text(pageNum);

                        for(var i = 1; i <= pageNum; i++) {
                            var canvas = document.createElement('canvas');
                            canvas.id = "pageNum" + i;
                            $("#imgDiv").append(canvas);
                            var context = canvas.getContext('2d');
                            openPage(pdf, i, context);
                        }
                    }
	            });
	        };
	    }
    });

    function openPage(pdfFile, pageNumber, context) {
        var scale = 2;
        pdfFile.getPage(pageNumber).then(function(page) {
            viewport = page.getViewport(scale); // reference canvas via context
            var canvas = context.canvas;
            canvas.width = viewport.width;
            canvas.height = viewport.height;
            canvas.style.width = "100%";
            canvas.style.height = "100%";
            var renderContext = {
                canvasContext: context,
                viewport: viewport
            };
            page.render(renderContext);
        });
		return;
    };

    $("#export").click(function () {

        var canvas = document.getElementById("pageNum1");
        var images = canvas.toDataURL();
        dcce_voa.Office.applist_pdftoimg.Save(images);

    });
           

.cs代碼:

[AjaxMethod()]
public void Save(string imgData)
{
    string filepath = "";
    //string imgData = Request["url"].ToString();
    var date = DateTime.Now.ToString("yyyyMMddmsms");
    if (imgData.StartsWith("data:image/png;base64") == true)
    {
        var base64 = imgData.Substring(22);
        byte[] bytes = Convert.FromBase64String(base64);
        MemoryStream memStream = new MemoryStream(bytes);
        BinaryFormatter binFormatter = new BinaryFormatter();
        var img = System.Drawing.Image.FromStream(memStream);
        filepath = "~/images/output/" + date + ".png";
        if (!Directory.Exists(Server.MapPath("~/images/output")))
        {
            Directory.CreateDirectory(Server.MapPath("~/images/output"));
        }
        img.Save(Server.MapPath(filepath));
    }
}