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));
}
}