使用ITextSharp和mvc损坏了pdf

时间:2011-05-20 15:32:36

标签: asp.net-mvc pdf-generation itextsharp

我正在尝试从MVC3网页生成pdf。我已经查看了所有常用的教程,但是当人们匆忙并且不知道自己在做什么的时候经常会这样,我正在制作狗的早餐。

当我单击视图上的操作链接以生成pdf时,该文件似乎已创建,但是当我尝试打开它时,我从Adobe Reader获得了一条非常有用的消息:“...文件是损坏,无法修复“。

我哪里出错?

    public FileStreamResult PDFGenerator()
    {
        Stream fileStream = GeneratePDF();

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

        return new FileStreamResult(fileStream, "application/pdf");
    }

    private Stream GeneratePDF()
    {
        MemoryStream ms = new MemoryStream();

        Document doc = new Document();
        PdfWriter writer = PdfWriter.GetInstance(doc, ms);
        doc.Open();
        doc.Add(new Paragraph("Hello"));

        ms.Position = 0;
        ms.Flush();

        writer.Flush();

        return ms;
    }

1 个答案:

答案 0 :(得分:3)

您必须关闭文档。试试这样:

public ActionResult PDFGenerator()
{
    var doc = new Document();
    using (var stream = new MemoryStream())
    {
        var writer = PdfWriter.GetInstance(doc, stream);
        doc.Open();
        doc.Add(new Paragraph("Hello"));
        doc.Close();
        return File(stream.ToArray(), "application/pdf", "test.pdf");
    }
}

但那很难看。我建议你更多MVCish方法,包括编写自定义ActionResult。另外一个优点是,您的控制器操作将更容易单独进行单元测试:

public class PdfResult : FileResult
{
    public PdfResult(): base("application/pdf")
    { } 

    public PdfResult(string contentType): base(contentType)
    { }

    protected override void WriteFile(HttpResponseBase response)
    {
        var cd = new ContentDisposition
        {
            Inline = false,
            FileName = "test.pdf"
        };
        response.AppendHeader("Content-Disposition", cd.ToString());

        var doc = new Document();
        var writer = PdfWriter.GetInstance(doc, response.OutputStream);
        doc.Open();
        doc.Add(new Paragraph("Hello"));
        doc.Close();
    }
}

然后在你的控制器动作中:

public ActionResult PDFGenerator()
{
    return new PdfResult();
}

当然这可以更进一步,让PdfResult将视图模型作为构造函数参数,并根据此视图模型的某些属性生成PDF:

public ActionResult PDFGenerator()
{
    MyViewModel model = ...
    return new PdfResult(model);
}

现在情况开始好看了。