先下載 pdfjs:https://github.com/mozilla/pdf.js
目前最新版本是 4.0.379
把需要的文件放到項目下面,由於最新的 pdfjs 使用的 mjs,看情況可以加下 MIME 類型:
var provider = new FileExtensionContentTypeProvider(); provider.Mappings[".mjs"] = "application/javascript"; provider.Mappings[".ftl"] = "application/x-freemarker"; app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
然後把 PDF 文件轉 base64
public static string Pdf2Base64(string inputPath) { byte[] fileBytes = System.IO.File.ReadAllBytes(inputPath); return Convert.ToBase64String(fileBytes); }
我們定義個 Model ,把 PDF 的 base64 字符串傳給 View
public class DefaultModel { public string PdfBase64 { get; set; } } public IActionResult Index() { DefaultModel dm=new DefaultModel(); dm.PdfBase64 = PdfHelper.Pdf2Base64("F:\\pdf\\compressed.tracemonkey-pldi-09.pdf"); return View(dm); }
然後根據示例:https://mozilla.github.io/pdf.js/examples/ ,在 View 中顯示 PDF:
<script src="~/pdfjs/js/pdf.mjs" type="module"></script> <script type="module"> // atob() is used to convert base64 encoded PDF to binary-like data. // (See also https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/ // Base64_encoding_and_decoding.) var pdfData = atob('@Html.Raw(Model.PdfBase64)'); // Loaded via <script> tag, create shortcut to access PDF.js exports. var { pdfjsLib } = globalThis; // The workerSrc property shall be specified. pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdfjs/js/pdf.worker.mjs'; // Using DocumentInitParameters object to load binary data. var loadingTask = pdfjsLib.getDocument({data: pdfData}); loadingTask.promise.then(function(pdf) { console.log('PDF loaded'); // Fetch the first page var pageNumber = 1; pdf.getPage(pageNumber).then(function(page) { console.log('Page loaded'); var scale = 1.5; var viewport = page.getViewport({scale: scale}); // Prepare canvas using PDF page dimensions var canvas = document.getElementById('the-canvas'); var context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; // Render PDF page into canvas context var renderContext = { canvasContext: context, viewport: viewport }; var renderTask = page.render(renderContext); renderTask.promise.then(function () { console.log('Page rendered'); }); }); }, function (reason) { // PDF loading error console.error(reason); }); </script>
在頁面上添加,就可以顯示 pdf 了
<canvas id="the-canvas"></canvas>
不過這樣我們只顯示了 PDF 的第一頁
對於多頁 PDF ,我們還需要修改下,先加上文檔的頁面顯示,再加上 上一頁、下一頁 的按鈕,修改後的 HTML 如下:
<div class="text-center"> <button id="prev">上一頁</button> <button id="next">下一頁</button> <span>Page: <span id="page_num"></span> / <span id="page_count"></span></span> </div> <canvas id="the-canvas"></canvas> </div>
然後修改下 js 代碼:
<script src="~/pdfjs/js/pdf.mjs" type="module"></script> <script type="module"> var pdfDoc = null; var pageStartNum = 1; var pageEndNum = 1; var pageNum = 1; var pdfData = safeAtob('@Html.Raw(Model.PdfBase64)'); // Loaded via <script> tag, create shortcut to access PDF.js exports. var { pdfjsLib } = globalThis; // The workerSrc property shall be specified. pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdfjs/js/pdf.worker.mjs'; // Using DocumentInitParameters object to load binary data. var loadingTask = pdfjsLib.getDocument({ data: pdfData }); loadingTask.promise.then(function (pdf) { console.log('PDF loaded'); pdfDoc = pdf; pageEndNum = pdfDoc.numPages; document.getElementById('page_count').textContent = pageEndNum; // Fetch the first page renderPage(pageNum); }, function (reason) { // PDF loading error console.error(reason); }); function renderPage(pageNumber) { pdfDoc.getPage(pageNumber).then(function (page) { console.log('Page ' + pageNumber + ' loaded'); var scale = 1.5; var viewport = page.getViewport({ scale: scale }); // Prepare canvas using PDF page dimensions var canvas = document.getElementById('the-canvas'); var context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; // Render PDF page into canvas context var renderContext = { canvasContext: context, viewport: viewport }; var renderTask = page.render(renderContext); renderTask.promise.then(function () { console.log('Page rendered'); }); }); document.getElementById('page_num').textContent = pageNumber; }; function safeAtob(base64Str) { // 檢查輸入字符串是否是有效的Base64編碼 console.log(base64Str.length); const base64Regex = /^[A-Za-z0-9+/]+={0,2}$/; if (!base64Regex.test(base64Str)) { throw new Error('The string to be decoded is not correctly encoded.'); } // 如果輸入字符串長度不是4的倍數,添加等號'=' while (base64Str.length % 4 !== 0) { base64Str += '='; } return atob(base64Str); } /** * Displays previous page. */ function onPrevPage() { if (pageNum <= pageStartNum) { return; } pageNum--; renderPage(pageNum); } document.getElementById('prev').addEventListener('click', onPrevPage); /** * Displays next page. */ function onNextPage() { if (pageNum >= pageEndNum) { return; } pageNum++; renderPage(pageNum); } document.getElementById('next').addEventListener('click', onNextPage); </script>
看下效果:
顯示完成了
下一步結合上一篇:https://www.cnblogs.com/sun8134/p/18109237
我們給 PDF 文件實時加上水印
修改下我們文件轉 base64 的方法:
public static string PdfWatermark2Base64(string inputPath, string watermarkImage, string watermarkTxt) { MemoryStream outputStream = new MemoryStream(); using (PdfReader existingPdf = new PdfReader(inputPath)) { using (PdfWriter newPdf = new PdfWriter(outputStream)) { using (PdfDocument pdfDocument = new PdfDocument(existingPdf, newPdf)) { Document document = new Document(pdfDocument); iText.Kernel.Geom.Rectangle pageSize; PdfCanvas canvas; var image = new iText.Layout.Element.Image(iText.IO.Image.ImageDataFactory.Create(watermarkImage)).ScaleToFit(200, 200); PdfFont fonts = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN); //PdfFont fontChinese; //var path = System.IO.Path.Combine("F:\\pdf", "font.ttf"); //fontChinese = PdfFontFactory.CreateFont(path, PdfEncodings.IDENTITY_H); int red = 51; int green = 53; int blue = 102; for (int i = 1; i <= pdfDocument.GetNumberOfPages(); i++) { PdfPage page = pdfDocument.GetPage(i); pageSize = page.GetPageSize(); canvas = new PdfCanvas(page); Paragraph p = new Paragraph(); p.Add(image); p.SetFont(fonts); p.Add(new Text("\r\n")); p.Add(new Text(watermarkTxt).SetFontSize(90).SetFontColor(new DeviceRgb((float)red / 255f, (float)green / 255f, (float)blue / 255f))); p.Add(new Text("\r\n")); p.Add(new Text(DateTime.Now.ToString("yyyy-MM-dd HH:mm")).SetFontSize(60).SetFontColor(ColorConstants.DARK_GRAY)); canvas.SaveState(); PdfExtGState gs1 = new PdfExtGState().SetFillOpacity(0.4f); canvas.SetExtGState(gs1); document.ShowTextAligned(p, pageSize.GetWidth() / 2 - 50, pageSize.GetHeight() / 2 + 50, pdfDocument.GetPageNumber(page), TextAlignment.CENTER, VerticalAlignment.MIDDLE, 45); } document.Close(); pdfDocument.Close(); newPdf.Close(); existingPdf.Close(); } } } byte[] extractedPdfData = ((MemoryStream)outputStream).ToArray(); string base64 = Convert.ToBase64String(extractedPdfData); outputStream.Close(); outputStream.Dispose(); return base64; }
在控制器裏調用新方法:
public IActionResult Index() { DefaultModel dm=new DefaultModel(); dm.PdfBase64 = PdfHelper.PdfWatermark2Base64("F:\\pdf\\compressed.tracemonkey-pldi-09.pdf", "F:\\pdf\\netcore.png", "Asp.Net Core 8.0"); return View(dm); }
看下效果:
整體上雖然能看
但效果其實只能說一般
pdfjs 帶了一個 viewer.html
基本包含了全功能,下一篇說下怎麼改 viewer.html