使用 ITextSharp 和 mvc 损坏的 pdf

发布于 2024-11-08 06:12:59 字数 833 浏览 0 评论 0原文

我正在尝试从 MVC3 网页生成 pdf。我已经看过所有常见的教程,但就像经常出现的情况一样,当一个人很匆忙并且不知道自己在做什么时,我正在用它做狗的早餐。

当我单击视图上的操作链接来生成 pdf 时,该文件似乎已创建,但当我尝试打开它时,我从 Adob​​e 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;
    }

I am trying to generate a pdf out of an MVC3 webpage. I've viewed all the usual tutorials, but as is often the case when one is in a hurry and doesn't really know what one is doing, I'm making a dog's breakfast of it.

When I click the action link on the view to generate the pdf, the file appears to be created, but when I try to open it, I get the ever so helpful message from Adobe Reader that "... the file is damaged and cannot be repaired".

Where have I gone wrong?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绅士风度i 2024-11-15 06:12:59

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

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

但这很丑。我会向您推荐一种更加 MVC 的方法,其中包括编写自定义 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);
}

现在事情开始看起来不错。

You must close the document. Try like this:

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

But that's ugly. I would recommend you a more MVCish approach which consists in writing a custom ActionResult. As an additional advantage of this is that your controller actions will be more easier to unit test in isolation:

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

and then in your controller action:

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

Of course this can be taken a step further and have this PdfResult take a view model as constructor argument and generate the PDF based on some properties on this view model:

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

Now things are beginning to look nice.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文