поврежден PDF с использованием ITextSharp и mvc - PullRequest
1 голос
/ 20 мая 2011

Я пытаюсь создать PDF-файл из веб-страницы MVC3. Я просмотрел все обычные учебные пособия, но, как это часто бывает, когда кто-то спешит и не знает, что на самом деле делает, я готовлю из него собачий завтрак.

Когда я нажимаю ссылку действия в представлении, чтобы сгенерировать 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 Ответ

3 голосов
/ 20 мая 2011

Вы должны закрыть документ.Попробуйте вот так:

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

Теперь все начинает выглядеть красиво.

...