如何在MVC中将PDF返回到浏览器?

Ton*_*orf 117 c# pdf asp.net asp.net-mvc itextsharp

我有这个iTextSharp的演示代码

    Document document = new Document();
    try
    {
        PdfWriter.GetInstance(document, new FileStream("Chap0101.pdf", FileMode.Create));

        document.Open();

        document.Add(new Paragraph("Hello World"));

    }
    catch (DocumentException de)
    {
        Console.Error.WriteLine(de.Message);
    }
    catch (IOException ioe)
    {
        Console.Error.WriteLine(ioe.Message);
    }

    document.Close();
Run Code Online (Sandbox Code Playgroud)

如何让控制器将pdf文档返回到浏览器?

编辑:

运行此代码确实打开Acrobat但我收到一条错误消息"文件已损坏且无法修复"

  public FileStreamResult pdf()
    {
        MemoryStream m = new MemoryStream();
        Document document = new Document();
        PdfWriter.GetInstance(document, m);
        document.Open();
        document.Add(new Paragraph("Hello World"));
        document.Add(new Paragraph(DateTime.Now.ToString()));
        m.Position = 0;

        return File(m, "application/pdf");
    }
Run Code Online (Sandbox Code Playgroud)

任何想法为什么这不起作用?

Geo*_*off 125

回来一个FileContentResult.控制器操作的最后一行是:

return File("Chap0101.pdf", "application/pdf");
Run Code Online (Sandbox Code Playgroud)

如果要动态生成此PDF,最好使用a MemoryStream,并在内存中创建文档而不是保存到文件.代码如下:

Document document = new Document();

MemoryStream stream = new MemoryStream();

try
{
    PdfWriter pdfWriter = PdfWriter.GetInstance(document, stream);
    pdfWriter.CloseStream = false;

    document.Open();
    document.Add(new Paragraph("Hello World"));
}
catch (DocumentException de)
{
    Console.Error.WriteLine(de.Message);
}
catch (IOException ioe)
{
    Console.Error.WriteLine(ioe.Message);
}

document.Close();

stream.Flush(); //Always catches me out
stream.Position = 0; //Not sure if this is required

return File(stream, "application/pdf", "DownloadName.pdf");
Run Code Online (Sandbox Code Playgroud)

  • 无法将类型'System.Web.Mvc.FileStreamResult'隐式转换为'System.Web.Mvc.FileContentResult' (3认同)
  • 杰夫,我试图实现这一点,但遇到类似的问题.我在运行时收到错误"无法访问已关闭的流"但如果我不关闭它则不会返回任何内容. (2认同)

Ton*_*orf 60

我得到了它使用此代码.

using iTextSharp.text;
using iTextSharp.text.pdf;

public FileStreamResult pdf()
{
    MemoryStream workStream = new MemoryStream();
    Document document = new Document();
    PdfWriter.GetInstance(document, workStream).CloseStream = false;

    document.Open();
    document.Add(new Paragraph("Hello World"));
    document.Add(new Paragraph(DateTime.Now.ToString()));
    document.Close();

    byte[] byteInfo = workStream.ToArray();
    workStream.Write(byteInfo, 0, byteInfo.Length);
    workStream.Position = 0;

    return new FileStreamResult(workStream, "application/pdf");    
}
Run Code Online (Sandbox Code Playgroud)

  • 我有点担心在我能找到的任何例子中都没有一个`using`语句......这里不需要吗?我想你至少有3个一次性物品...... (9认同)
  • FileSteamResult将为您关闭流.请参阅此答案http://stackoverflow.com/a/10429907/228770 (6认同)

Mac*_*gon 20

您必须指定:

Response.AppendHeader("content-disposition", "inline; filename=file.pdf");
return new FileStreamResult(stream, "application/pdf")
Run Code Online (Sandbox Code Playgroud)

对于要在浏览器中直接打开而不是下载的文件


Ner*_*ury 16

如果FileResult从操作方法返回a ,并File()在控制器上使用扩展方法,那么执行您想要的操作非常简单.该File()方法有一些覆盖,它将采用文件的二进制内容,文件的路径或a Stream.

public FileResult DownloadFile()
{
    return File("path\\to\\pdf.pdf", "application/pdf");
}
Run Code Online (Sandbox Code Playgroud)


lit*_*ris 11

我遇到了类似的问题,我偶然发现了一个解决方案.我用了两个职位,一个从堆栈,显示返回下载和其他方法一个,显示了iTextSharp的和MVC工作方案.

public FileStreamResult About()
{
    // Set up the document and the MS to write it to and create the PDF writer instance
    MemoryStream ms = new MemoryStream();
    Document document = new Document(PageSize.A4.Rotate());
    PdfWriter writer = PdfWriter.GetInstance(document, ms);

    // Open the PDF document
    document.Open();

    // Set up fonts used in the document
    Font font_heading_1 = FontFactory.GetFont(FontFactory.TIMES_ROMAN, 19, Font.BOLD);
    Font font_body = FontFactory.GetFont(FontFactory.TIMES_ROMAN, 9);

    // Create the heading paragraph with the headig font
    Paragraph paragraph;
    paragraph = new Paragraph("Hello world!", font_heading_1);

    // Add a horizontal line below the headig text and add it to the paragraph
    iTextSharp.text.pdf.draw.VerticalPositionMark seperator = new iTextSharp.text.pdf.draw.LineSeparator();
    seperator.Offset = -6f;
    paragraph.Add(seperator);

    // Add paragraph to document
    document.Add(paragraph);

    // Close the PDF document
    document.Close();

    // Hat tip to David for his code on stackoverflow for this bit
    // https://stackoverflow.com/questions/779430/asp-net-mvc-how-to-get-view-to-generate-pdf
    byte[] file = ms.ToArray();
    MemoryStream output = new MemoryStream();
    output.Write(file, 0, file.Length);
    output.Position = 0;

    HttpContext.Response.AddHeader("content-disposition","attachment; filename=form.pdf");


    // Return the output stream
    return File(output, "application/pdf"); //new FileStreamResult(output, "application/pdf");
}
Run Code Online (Sandbox Code Playgroud)

  • 使用?关?处理?冲洗?谁在乎内存泄漏? (2认同)

Wei*_*Guo 5

FileStreamResult当然有效。但是如果您查看Microsoft Docs,它继承自ActionResult -> FileResult,它具有另一个派生类FileContentResult。它“将二进制文件的内容发送到响应”。因此,如果您已经拥有byte[],则应该FileContentResult改为使用。

public ActionResult DisplayPDF()
{
    byte[] byteArray = GetPdfFromWhatever();

    return new FileContentResult(byteArray, "application/pdf");
}
Run Code Online (Sandbox Code Playgroud)