2018年3月20日 星期二

[研究][ASP.NET] 動態網頁轉 pdf (使用免費 wkhtmltopdf.exe )

[研究][ASP.NET] 動態網頁轉 pdf (使用免費 wkhtmltopdf.exe )

2018-03-20

參考這兩篇

[研究][ASP.NET] 把 ASP.NET Webform 動態網頁轉成 HTML 靜態網頁
http://shaurong.blogspot.com/2018/03/aspnet-aspnet-webform-html.html

[研究] HTML to PDF (wkhtmltopdf) 命令列工具 + ASP.NET
http://shaurong.blogspot.com/2018/03/html-to-pdf-wkhtmltopdf-aspnet.html

先把 ASP.NET WebPage 轉成 HTML 靜態網頁,再用 wkhtmltopdf.exe 轉成 pdf 檔案。

為什麼這麼麻煩?
因為目前找到的 URL 或 ASP.NET WebPage 直接轉 pdf 的元件都是付費的, selectpdf 社群版和 Free Spire.PDF for .NET 是免費,但是轉出的 pdf 有頁數限制,除非買商業版;用 iText、iTextSharp、PDFsharp 產生 pdf 檔案非常麻煩。

環境:Visual Studio 2017 v15.6.3 + ASP.NET + WebForm +  wkhtmltopdf.exe

Default.aspx 內容為預設沒修改。

Default.aspx.cs 內容
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication2
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // 請不要轉換自己,否則下面 page.Server.Execute(path, writer); 會出現 「未處理的例外狀況 System.StackOverflowException」
            //transHtml("Default.aspx", "Default.htm");
            transHtml("WebForm1.aspx", "WebForm1.htm");

            string myPath = Server.MapPath("/");

            Process _process = new Process();
            _process.StartInfo.FileName = @"C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe";
            // _process.StartInfo.Arguments = @"http://www.google.com.tw  C:\temp\test.pdf";
            //_process.StartInfo.Arguments = @"http://www.google.com.tw  " + myPath + @"test.pdf";
            //_process.StartInfo.Arguments = myPath + @"Default.htm   " + myPath + @"Default.htm.pdf";
            _process.StartInfo.Arguments = myPath + @"WebForm1.htm   " + myPath + @"WebForm1.htm.pdf";
            _process.Start();

            // 等跑完後,開啟 pdf
            //while (_process.HasExited)
            //{
            //    //讓執行續暫停1秒 ( 1000ms)
            //    Thread.Sleep(30000);
            //}

            // System.ComponentModel.Win32Exception: '系統找不到指定的檔案。' 
            // => 原因不明,再跑一次,這次 pdf 已經存在,可順利開啟
            //Process.Start(@"C:\temp\test.pdf");
            //Process.Start(myPath + @"test.pdf");
        }

        public void transHtml(string path, string outpath)
        {
            System.Web.UI.Page page = new Page();
            StringWriter writer = new StringWriter();
            page.Server.Execute(path, writer);
            FileStream fs;
            fs = File.Create(page.Server.MapPath("") + "\\" + outpath);
            
            //繁體中文字會亂碼,必須強行指定 UTF8
            //byte[] bt = System.Text.Encoding.Default.GetBytes(writer.ToString());
            byte[] bt = System.Text.Encoding.UTF8.GetBytes(writer.ToString());

            fs.Write(bt, 0, bt.Length);
            fs.Close();
            Response.Write("寫入成功");
        }
    }
}

WebForm1.aspx 內容

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication2.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            測試<br />
            TEST
        </div>
    </form>
</body>
</html>


WebForm1.aspx.cs 為預設,沒有修改。

測試結果


注意,如果佈署 (deploy ) 到 IIS 上,可能要考慮目錄寫入權限。

(完)

沒有留言:

張貼留言