2013-05-02 42 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(); 
}