2012-10-26 6 views
8

私はC#Webアプリケーションから呼び出すwkhtmltopdf.exeを使用してHTMLドキュメントをPDFとしてレンダリングしようとしています。WkHtmlToPDF - stdinとヘッダ/フッタの使用

HTML文書には、すべてのページで繰り返されるフッターとヘッダーの両方が必要です。これは、引数として--header-html <a path>を指定してwkhtmltopdfで可能です。

しかし、フッタはRazorビューから動的にレンダリングされるので、ディスク上の一時ファイルに格納してそのパスを使用する必要はありませんが、すでにメモリ内にレンダリングされているHTMLを使用したいと考えています。それは、文書自体のため、そのように、StandardInputストリームに書き込むことによって可能です:

var wkhtml = ConfigurationManager.AppSettings["WkHtmlToPdfPath"]; 
var p = new Process(); 

p.StartInfo.CreateNoWindow = true; 
p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.RedirectStandardError = true; 
p.StartInfo.RedirectStandardInput = true; 
p.StartInfo.UseShellExecute = false; 
p.StartInfo.FileName = wkhtml; 

p.StartInfo.Arguments = "-q -n --disable-smart-shrinking - -"; 
p.Start(); 

var stdin = p.StandardInput; 
stdin.AutoFlush = true; 
stdin.Write(template); 
stdin.Dispose(); 

、すなわちに頼らずにインラインでそれを渡すために、ヘッダーとフッターHTMLのために同じことをすることは可能です一時ファイル?私が試した

stdin.Write(string.Format("--footer-html {0} ", footer)); 

しかし、もちろん、それだけで扱い、その文書ではなく、フッターの一部として。

私がフッターとヘッダーを動的にレンダリングしたい主な理由は(主に)別の問題によるものです。動的なヘッダとフッタを持つのは良いことですが、相対パス(例:C:\ templates \ images \ logo.png)が絶対パスであるため、 images/logo.png)は、stdinを使用してHTMLの文字列blobを渡すときには動作しませんので、実行時にRazorを通して絶対パスを挿入する必要があります。の90%を解決するでしょう

p.StartInfo.WorkingDirectory = @"C:\templates"; 

私はその問題を解決することができれば、:

この問題については

、私は相対パスを一致させるために、プロセスの作業ディレクトリを設定しようとしたが、無駄にしました問題も同様です。

+2

私は同じ問題を抱えていましたが、Wkhtmltopdfの脅威のヘッダー/フッターが(外部のパス/ URLを介して)別々になってしまったので、動的なデータをURLにフィードしたhtmlドキュメントを定義しました。私はいくつかのjavascriptでそれらを抽出しました。 – Alex

答えて

3

あなたがこのJulianRを解決したのであれば、私もあなたがMVC(?)であると仮定します。 以下の初期コードのいくつかを無視することができますが、 wkhtmltopdfには、サイトの安全なセクションとログインしたセクションがあります。

まずコントローラに、あなたが(それ自体はヘッダーとフッターを使用することができることに)適用されるマスターページで表示するために必要なビューで引くことができます。

var view = ViewEngines.Engines.FindView(ControllerContext, myViewName, myMasterPageLayout); 

は、あなたが、その後で、このビューの現在を取得しますどんななど必要なViewDataを、TempDataを、文字列(以下、コンテンツ)でこれを格納します。この段階で

string content; 
ViewData.Model = model; 
using (var writer = new System.IO.StringWriter()) 
{ 
    var context = new ViewContext(ControllerContext, view.View, ViewData, TempData, writer); 
    view.View.Render(context, writer); 
    writer.Flush(); 
    content = writer.ToString(); 
    writer.Close(); 
} 

必要であれば、あなたが実際に文字列であなたの出力HTMLを修正することができる - などあなたはHTMLを出力すると、完全なパスに

を任意のローカルパスを変更するために、あなたは、単にwkhtmltopdfに渡す:

var p = new Process(); 
p.StartInfo.CreateNoWindow = true; 
p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.RedirectStandardError = true; 
p.StartInfo.RedirectStandardInput = true; 
p.StartInfo.UseShellExecute = false; 
//Other parameters as required 
byte[] file; 
try 
{ 
    p.Start(); 
    byte[] buffer = new byte[32768]; 

    using (System.IO.StreamWriter stdin = p.StandardInput) 
    { 
     stdin.AutoFlush = true; 
     stdin.Write(content); 
    } 


    using (MemoryStream ms = new MemoryStream()) 
    { 
     ms.Position = 0; 
     p.StandardOutput.BaseStream.CopyTo(ms); 
     file = ms.ToArray(); 
    } 

    p.StandardOutput.Close(); 
    // wait or exit 
    p.WaitForExit(60000); 

    // read the exit code, close process 
    int returnCode = p.ExitCode; 

} 

あなたがして、ページ全体のあなたのPDFコンテンツを含むバイト配列を持っています。

+0

情報ありがとうございます。私はこの問題を解決することなく、代わりにレポートを編集する際にかなりぎこちなくても、多数の利点(シンプルさ、ネイティブ印刷のサポート)を持ったMicrosoft RDLCレポートを使用しました。 – JulianR

関連する問題