2012年10月16日 星期二

[Asp].實作網頁匯出為 PDF 的心得

今天分享我在實作網頁匯出為 PDF 的心得, 今天遇到2個問題:
Q 1. 在後台匯出的網頁, 要匯出的網頁必需為 "登錄狀態" 才能匯出, 可是使用 wkhtmltopdf 時, 無法取得登入狀態.
Q 2. wkhtmltopdf 元件匯出的資料夾, 無法和中文目錄相容, 會有Error 產生, 訊息如下:
匯出檔案到 E:\oooo網\ 這個 "網" 是中文字, 造成Error.


Q 1. 首先解決, 登錄狀態, 的問題,
A 1: 這個解決方法很多很多,

方案1.1: 直接輸入 userid.
這是最快的解決方法, 直接寫一支 app_sso.asp 程式, 傳入 userid 就解決了. 可是這個解法變成, 萬一我是離職的工程師, 我事先就知道這支程式, 在user 傳入 userid 就可以取得該帳號的權限, 這樣問題就比較大.


方案1.2: 修改後台的程式, 遇到某些參數傳進來時(例如: ?exportPdf=true), 就開放部份的權限, 允許顯示資料庫內容. 這個解法也不錯.


方案1.3: session userid 放database, 透過 tokenid 來存取.
和上面的方案1.1相比, 這個方案1.3 會安全一點點, app_sso.asp 處理步驟如下:

1.3.1. 後台把 session userid 放進 table,
1.3.2. 取出 table 裡的 token_id,
1.3.3. 把 token_id 給下一支沒有 session 的 app,
1.3.4. 沒有 session 的 app request token_id 後, 透過 tokenid 再到 database 裡去取出 userid.
1.3.5 模擬使用者登入, 並重導(Redirect) 到實際上要產生為 PDF 的 URL.


附上使用到的 table schema:
CREATE TABLE [dbo].[webkitHtmlToken](
 [id] [int] IDENTITY(1,1) NOT NULL,
 [tokenID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_webkitHtmlToken_tokenId]  DEFAULT (newid()),
 [userid] [nvarchar](20) NOT NULL,
 [siteid] [varchar](50) NULL,
 [status] [char](1) NULL CONSTRAINT [DF_webkitHtmlToken_status]  DEFAULT ('I'),
 [sessionid] [int] NULL,
 [createdDate] [smalldatetime] NULL CONSTRAINT [DF_webkitHtmlToken_createdDate]  DEFAULT (getdate()),
 CONSTRAINT [PK_webkitHtmlToken] PRIMARY KEY CLUSTERED
(
 [tokenID] ASC
)
)
說明: 可能專案不同, 有可能需要多增加, 或刪除相關欄位.


Q 2: 中文字,
A 2:這個要解就很簡單, 先透過副程式判斷是否有中文字, 有的話就使用暫存的資料夾.


最後, 整個流程方式, 我的做法是:
2.1 在AP設定檔裡增加2個設定值,
(a)wkhtmltopdf 執行檔路徑
(b)wkhtmltopdf 遇到中文字路徑時, 要使用的暫存資料夾, 這個記得要允許 IUSER 有寫入及刪除檔案的權限, 例如:
<wkhtmltopdf>
    <path>C:\wkhtmltopdf\wkhtmltopdf.exe</path>
    <tempFolder>C:\wkhtmltopdf\tempFolder</tempFolder>
</wkhtmltopdf>

2.2 寫副程式, 取得 tokenid
'// purpose: 放入 session info 到 database, 取得 tokenid.
'// ex: ret = getWebkitHtmlTokenID(conn, session("userid"), session.sessionid, session("siteid"))
function getWebkitHtmlTokenID(byref conn, byval userid, byval sessionid, byval siteid)
...
...
end function


2.3 寫副程式, 取得 tokenid
'// purpose: 輸出某一個 URL 到實體檔案.
'// call HtmlToPdfFile(pdfUrl, user_output_filepath)
function HtmlToPdfFile(byval pdfUrl, user_output_filepath)
...
...
end function

2.4 寫一支  export_pdf.asp
2.4.1 先呼叫 2.2 的附程式取得 tokenID.
2.4.2 再把 tokenID 放入 app_sso.asp, 並設定實際要匯入資料的 URL.
2.4.3 輸出某一個 URL 到實體檔案, 在這個副程式裡執行外部指令(要等待程式回應, Wait For Single), 等待wkhtmltopdf.exe 匯出pdf 完成程式再繼續往下執行.
2.4.4 透過 ADODB.Stream, 取出檔案內容, 並 Response.BinaryWrite objStream.Read
2.4.5 最後, 完成後, 刪掉暫存檔, 後台匯出pdf 完成.
call DeleteFile(user_output_filepath)


說明: 前台(無登錄狀態)匯出 pdf 的話就會簡單很多, 少掉取得 tokenid 這一個 step.

增加這個功能, 會用到的相關檔案及說明:


  • ApConfig.xml , 參數設定
  • app_sso.asp , 讓外部程式模擬登入
  • export_pdf.asp , 實際上匯出的 app.
  • pdf.Function.asp , 副程式.





相關文章:
[Asp].用正規表示式檢查字串是不包含中文字
http://maxtellyou.blogspot.tw/2012/10/asp.html

3 則留言:

  1. 作者已經移除這則留言。

    回覆刪除
  2. 請問要怎麼會出PDF呢?
    我還是看不太懂...
    謝謝

    回覆刪除
  3. 您好:是否可以教我怎麼用asp去呼叫wkhtmltopdf此DOS指令呢??非常感謝您~~

    回覆刪除

Facebook 留言板