2013-05-02 39 views
1

我产生在Azure中的VM使用Prince XML(通过Web角色)的PDF文件。用PdfFilter()属性标记的操作方法将HTML转发给Prince XML;一旦PDF已经建立,新的文件是使用下面的代码写入到客户端:PDF文件下载与使用C#,MVC3和.NET 3.5 0字节的文件

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 - 这是不可用的。

有没有被抛出任何异常,和王子XML日志文件表明都已成功生成的文件。我已经通过C#验证了远程桌面到Azure虚拟机中的PDF文件,这些文件真的是通过PDF阅读器创建和读取的。

还有什么我可能会丢失?提前致谢!

回答

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(); 
}