Gayhub 連結
問遍Google百度,依然沒有好的方案.
開啟Gayhub ,發現萬贊JS 效果也就那個XX樣,一張糊裡糊塗的img 冒充精美的PDF?
經過一天的苦思冥想,藉助HiqPDF (估計Itext , spirePDF 等類似的都可以,思路還用這個就可以了),終於實現了目前來看最完美的方案 - -而且,賊簡單你敢信?
<img src="https://github.com/yshch2008/perfecthtml2pdf_with_Hiq/blob/master/timg2.jpg"/>
先來個 (= ̄ω ̄=)
<img src="https://github.com/yshch2008/perfecthtml2pdf_with_Hiq/blob/master/git_index.png"/>
簡單版本,讀檔案 - -好處是無視網站定製,壞處當然就是非自動化啦(,,・ω・,,)
在你的後台放一個接收器,java,golang,python版本的 ,改天懶癌減輕了就補:
public ActionResult getWOW() { FileStream fs = new FileStream(Server.MapPath("/App_Data/wow.txt"), FileMode.OpenOrCreate, FileAccess.Read);//路徑 StreamReader sr = new StreamReader(fs, Encoding.UTF8); var htm = sr.ReadToEnd(); sr.Close(); fs.Close(); // create the HTML to PDF converter HtmlToPdf htmlToPdfConverter = new HtmlToPdf(); // set browser width htmlToPdfConverter.BrowserWidth = 1440; // set browser height if specified, otherwise use the default htmlToPdfConverter.BrowserHeight = htmlToPdfConverter.BrowserWidth * 2; // set HTML Load timeout //htmlToPdfConverter.HtmlLoadedTimeout = int.Parse(textBoxLoadHtmlTimeout.Text); // set PDF page size and orientation //htmlToPdfConverter.Document.PageSize = new PdfPageSize((float)(width / 2.4), (float)(height / 2.4)); htmlToPdfConverter.Document.PageSize = new PdfPageSize(htmlToPdfConverter.BrowserWidth, htmlToPdfConverter.BrowserHeight); htmlToPdfConverter.Document.PageOrientation = PdfPageOrientation.Portrait; // set the PDF standard used by the document htmlToPdfConverter.Document.PdfStandard = PdfStandard.Pdf;//checkBoxPdfA.Checked ? PdfStandard.PdfA : // set PDF page margins htmlToPdfConverter.Document.Margins = new PdfMargins(0); // set whether to embed the true type font in PDF htmlToPdfConverter.Document.FontEmbedding = true; // set triggering mode; for WaitTime mode set the wait time before convert htmlToPdfConverter.TriggerMode = ConversionTriggerMode.Auto; // set header and footer //SetHeader(htmlToPdfConverter.Document); //SetFooter(htmlToPdfConverter.Document); // set the document security //htmlToPdfConverter.Document.Security.OpenPassword = textBoxOpenPassword.Text; htmlToPdfConverter.Document.Security.AllowPrinting = true; // set the permissions password too if an open password was set if (htmlToPdfConverter.Document.Security.OpenPassword != null && htmlToPdfConverter.Document.Security.OpenPassword != String.Empty) htmlToPdfConverter.Document.Security.PermissionsPassword = htmlToPdfConverter.Document.Security.OpenPassword + "_admin"; //Cursor = Cursors.WaitCursor; // convert HTML to PDF string pdfFile = null; // convert URL to a PDF memory buffer //string url = formCollection["textBoxUrl"]; byte[] pdfBuffer = htmlToPdfConverter.ConvertHtmlToMemory(htm, null); // send the PDF document to browser FileResult fileResult = new FileContentResult(pdfBuffer, "application/pdf"); fileResult.FileDownloadName = "HtmlToPdf.pdf"; return File(pdfBuffer, "application/octet-stream", "test.pdf");//最後一個雙引號裡面是回傳的檔案名稱,加個time值就可以避免重複了 }
在瀏覽器按F12開啟控制台(console)輸入document.getElementsByTagName("html")[0].innerHTML
把得到的字串拷貝到路徑儲存
然後把伺服器跑起來,啟用一下這個controller "http://localhost:3095/"
然後你就就會下載一個PDF,開啟看看,激不激動?開不開心?
進階版本- -前後端互動
- Controller:
public ActionResult GetPDFfromHtmlCode(int width, int height, string htm) { htm = Server.UrlDecode(htm); //var path = Server.MapPath("/").Replace("\\", "/"); var path = @"C:\Users\Public\Documents\DevExpress Demos 18.1\Components\ASP.NET\CS\ASPxCardViewDemos"; htm = htm.Replace("/Content/",path+ "/Content/") .Replace("src=\"", "src=\""+path) //.Replace("<script src=\"", "<script src=\"" + path) //.Replace("type=\"text/css\" href=\"", "type=\"text/css\" href=\"" + path) .Replace("//","/") ; // create the HTML to PDF converter HtmlToPdf htmlToPdfConverter = new HtmlToPdf(); // set browser width htmlToPdfConverter.BrowserWidth = 1440; // set browser height if specified, otherwise use the default htmlToPdfConverter.BrowserHeight = height; // set HTML Load timeout //htmlToPdfConverter.HtmlLoadedTimeout = int.Parse(textBoxLoadHtmlTimeout.Text); // set PDF page size and orientation //htmlToPdfConverter.Document.PageSize = new PdfPageSize((float)(width / 2.4), (float)(height / 2.4)); htmlToPdfConverter.Document.PageSize = new PdfPageSize(htmlToPdfConverter.BrowserWidth, height); htmlToPdfConverter.Document.PageOrientation = PdfPageOrientation.Portrait; // set the PDF standard used by the document htmlToPdfConverter.Document.PdfStandard = PdfStandard.Pdf;//checkBoxPdfA.Checked ? PdfStandard.PdfA : // set PDF page margins htmlToPdfConverter.Document.Margins = new PdfMargins(0); // set whether to embed the true type font in PDF htmlToPdfConverter.Document.FontEmbedding = true; // set triggering mode; for WaitTime mode set the wait time before convert htmlToPdfConverter.TriggerMode = ConversionTriggerMode.Auto; // set header and footer //SetHeader(htmlToPdfConverter.Document); //SetFooter(htmlToPdfConverter.Document); // set the document security //htmlToPdfConverter.Document.Security.OpenPassword = textBoxOpenPassword.Text; htmlToPdfConverter.Document.Security.AllowPrinting = true; // set the permissions password too if an open password was set if (htmlToPdfConverter.Document.Security.OpenPassword != null && htmlToPdfConverter.Document.Security.OpenPassword != String.Empty) htmlToPdfConverter.Document.Security.PermissionsPassword = htmlToPdfConverter.Document.Security.OpenPassword + "_admin"; //Cursor = Cursors.WaitCursor; // convert HTML to PDF string pdfFile = null; // convert URL to a PDF memory buffer //string url = formCollection["textBoxUrl"]; byte[] pdfBuffer = htmlToPdfConverter.ConvertHtmlToMemory(htm, null); // send the PDF document to browser FileResult fileResult = new FileContentResult(pdfBuffer, "application/pdf"); fileResult.FileDownloadName = "HtmlToPdf.pdf"; return File(pdfBuffer, "application/octet-stream","test.pdf"); }
- JS裡面這個啟用(注意轉譯html):
var DownLoadFile = function (options) { var config = $.extend(true, { method: 'post' }, options); var $iframe = $('<iframe id="down-file-iframe" />'); var $form = $('<form target="down-file-iframe" method="' + config.method + '" />'); $form.attr('action', config.url); for (var key in config.data) { $form.append('<input type="hidden" name="' + key + '" value="' + config.data[key] + '" />'); } $iframe.append($form); $(document.body).append($iframe); $form[0].submit(); $iframe.remove(); } DownLoadFile({ url: "http://localhost:3095/test/getPDFfromHtmlCode", //the URI of your controller data: { "height": $("body").outerHeight(), "width": $("body").outerWidth(), "htm": escape(document.getElementsByTagName("html")[0].innerHTML), "head": "test" }//the data in your request ,according to your controller });
最後說明
首先你要轉的網頁最好資源檔都是絕對路徑的,因為巧婦難為無米之炊 ,你的伺服器拿不到資源檔去渲染,當然就做不到給你一個完美的PDF
其次,如果是相對路徑, 你需要在後端用replace大法,把相對路徑轉成伺服器能獲得的絕對路徑
再其次,終極辦法就是把網頁裡面的左右資源檔,你都給手動下載到伺服器上,然後把相對位址都引用到這個位置, 除了太神奇的樣式,基本都可以做到所見即所得 (WYSIWYG)
免費版本的hiqPDF會在檔案的頁首位置打浮水印 ,這個時候就體現我們方法的好處了:匯出的PDF不是圖片而是真的PDF編碼,所以可以用福昕 PDF 之類的軟體開啟把這個浮水印刪除掉
(當然你也可以在後端直接替換編碼,我這就不搞了,眼睛疼(๑´ڡ`๑))
開動一下腦筋,其實配合Markdown,線上Excel ,線上簡曆設計等等 東西,你可以很輕鬆的得到一份好看的PDF格式的 文檔,圖表,簡曆 ~~
所以不要糾結於My Code是否好看,主要是思路 - -遇山劈山,逢海填海 :前端沒法很好的渲染,那就放到後端; 後端拿不到相對路徑 ,就轉成絕對路徑;手動麻煩 ,就封裝成POST ,配合編解碼函數`````
你看,html2canvas 2pdf 都有那麼多的贊,效果其實就一張模糊的圖片 ,而我們,用一個簡單低級的思路, 得到了一份幾乎完美的PDF檔案 ,所以,思路啊老鐵~~
聲明:
- 無意支援盜版,大家有hiqPDF使用權的就用就好了,試用免費版本的也不觸犯法律,效果還是可以的~~
- 對於非開發人員或者純前端 ,這個方法還是稍微有點成本的 ,在此表示歉意
- 介於第二點 ,我準備在工作安穩一點後搭建一個線上的網站, 實現思路已經有了,希望到時候有志同道合的大佬們多給建議,多給協助~~
既然你都看到這裡了,滑鼠移到右上方給個star咯 ( ¯ ³¯)♡ㄘゅ