1

C#、MVC3、および .NET 3.5 を使用して、(Web ロールによって) Azure VM でPrince XMLを使用して PDF ファイルを生成しています。属性でタグ付けされたアクション メソッドはPdfFilter()、HTML を Prince XML に転送します。PDF が作成されると、次のコードを使用して新しいファイルがクライアントに書き込まれます。

public class PdfFilterAttribute : ActionFilterAttribute
{
    private HtmlTextWriter tw;
    private StringWriter sw;
    private StringBuilder sb;
    private HttpWriter output;

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // Hijack the HttpWriter and write it to a StringBuilder instead of the normal response (http://goo.gl/RCNey).
        sb = new StringBuilder();
        sw = new StringWriter(sb);
        tw = new HtmlTextWriter(sw);
        output = (HttpWriter)context.RequestContext.HttpContext.Response.Output;
        context.RequestContext.HttpContext.Response.Output = tw;
    }

    public override void OnResultExecuted(ResultExecutedContext context)
    {
        // Get the HTML from the request.
        string html = sb.ToString();

        // PdfController is where the PDF generation logic lives; instantiate it.
        var pdfController = new PdfController();

        // Generate a user-friendly filename for the PDF.
        string filename = pdfController.GetPdfFilename(html);

        // Generate the PDF and convert it to a byte array.
        FileInfo pdfInfo = pdfController.HtmlToPdf(html);

        // If the PDF or a user-friendly filename could not be generated, return the raw HTML instead.    
        if (pdfInfo == null || !pdfInfo.Exists || pdfInfo.Length == 0 || String.IsNullOrWhitespace(filename))
        {
            output.Write(html);
            return;
        }

        // If a PDF was generated, stream it to the browser for downloading.
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.AddHeader("Content-Type", "application/pdf");
        context.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\";");
        context.HttpContext.Response.WriteFile(pdfInfo.FullName);
        context.HttpContext.Response.Flush();
        context.HttpContext.Response.Close();
        context.HttpContext.Response.End();
    }
}

サーバー上でPDFが正常に作成されていることを確認しました。しかし、 を呼び出してクライアントに送り返そうとすると、Response.WriteFile()クライアントはダウンロードを 0 バイトの PDF としてのみ表示します。これは使用できません。

スローされる例外はなく、Prince XML ログ ファイルは、ファイルがすべて正常に生成されたことを示しています。私は、C# および Azure VM へのリモート デスクトップ接続によって、PDF が実際に作成され、PDF リーダーを介して読み取り可能であることを確認しました。

私が見逃している可能性のあるものは他にありますか?前もって感謝します!

4

1 に答える 1

0

私は自分の問題を解決しました-PDFをバイト配列として扱い、別の方法を使用してバイトを応答に書き込み、追加のヘッダーを追加してPDFのサイズを定義するようです。まだ 100% クリーンではありませんが、期待どおりに機能しています。

public override void OnResultExecuted(ResultExecutedContext context)
{
    // Get the HTML from the request.
    string html = sb.ToString();

    // PdfController is where the PDF generation logic lives; instantiate it.
    var pdfController = new PdfController();

    // Generate a user-friendly filename for the PDF.
    string filename = pdfController.GetPdfFilename(html);

    // Generate the PDF and convert it to a byte array.
    FileInfo pdfInfo = pdfController.HtmlToPdf(html);

    // Render the PDF as a byte array; if it can't be rendered, use an empty byte array instead.
    byte[] pdfBytes = (pdfInfo.Exists && pdfInfo.Length > 0 ? File.ReadAllBytes(pdfInfo.FullName) : new byte[]{});

    // If the PDF or a user-friendly filename could not be generated, return the raw HTML instead.    
    if (pdfBytes.Length == 0 || String.IsNullOrWhitespace(filename))
    {
        output.Write(html);
        return;
    }

    // If a PDF was generated, stream it to the browser for downloading.
    context.HttpContext.Response.Clear();
    context.HttpContext.Response.AddHeader("Content-Type", "application/pdf");
    context.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\";");
    context.HttpContext.Response.AddHeader("Content-Length", pdfBytes.Length.ToString());
    output.WriteBytes(pdfBytes, 0, pdfBytes.Length);
    context.HttpContext.Response.Flush();
    context.HttpContext.Response.Close();
    context.HttpContext.Response.End();
}
于 2013-05-06T13:45:42.833 に答える