【问题标题】:PDF files generated in Azure VM downloaded as 0 byte filesAzure VM 中生成的 PDF 文件下载为 0 字节文件
【发布时间】:2013-05-02 00:15:12
【问题描述】:

我正在使用 C#、MVC3 和 .NET 3.5 在 Azure VM(通过 Web 角色)中使用 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 阅读器在那里读取。

还有什么我可能会遗漏的吗?提前致谢!

【问题讨论】:

    标签: c# pdf-generation httpresponse azure-web-roles princexml


    【解决方案1】:

    我解决了自己的问题——似乎将 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();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-12
      • 2019-08-13
      • 2011-04-04
      • 2019-06-16
      • 2021-08-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多