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