8

C#Webアプリケーションから呼び出すwkhtmltopdf.exeを使用して、HTMLドキュメントをPDFとしてレンダリングしようとしています。

--header-html <a path>HTMLドキュメントには、すべてのページで繰り返されるフッターとヘッダーの両方が必要です。これは、引数として指定することで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));

しかしもちろん、それはフッターではなく、ドキュメントの一部として扱われます。

フッターとヘッダーも動的にレンダリングしたい主な理由は、(ほとんど)別の問題が原因です。動的なヘッダーとフッターがあると便利ですが、相対パス(例: images / logo.png)stdinを使用し、HTMLの文字列blobを渡すだけでは機能しないため、実行時にRazorを介して絶対パスを挿入する必要があります。

この問題では、相対パスと一致するようにプロセスの作業ディレクトリを設定しようとしましたが、役に立ちませんでした。

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

その問題を解決できれば、問題の90%も解決します。

4

1 に答える 1

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 コンテンツを含むバイト配列を取得します。

于 2013-09-12T12:59:46.517 に答える