Làm cách nào để trả lại PDF về trình duyệt trong MVC?


120

Tôi có mã demo này cho 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();

Làm cách nào để tôi yêu cầu bộ điều khiển trả lại tài liệu pdf cho trình duyệt?

BIÊN TẬP:

Chạy mã này không mở được Acrobat nhưng tôi nhận được thông báo lỗi "Tệp bị hỏng và không thể sửa chữa được"

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

Bất kỳ ý tưởng tại sao điều này không hoạt động?



@ mg1075 liên kết của bạn đã chết
thecoolmacdude

Câu trả lời:


128

Trả lại a FileContentResult. Dòng cuối cùng trong hành động điều khiển của bạn sẽ giống như sau:

return File("Chap0101.pdf", "application/pdf");

Nếu bạn đang tạo động PDF này, có thể tốt hơn là sử dụng a MemoryStreamvà tạo tài liệu trong bộ nhớ thay vì lưu vào tệp. Mã sẽ giống như sau:

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

@Tony, trước tiên bạn cần đóng tài liệu và xả luồng.
Geoff

2
Geoff, tôi đang cố gắng đạt được điều này, nhưng gặp vấn đề tương tự. Tôi gặp lỗi lúc chạy "Không thể truy cập Luồng đã đóng" Nhưng nếu tôi không đóng thì sẽ không có gì được trả lại.
littlechris

1
Cảm ơn @littlechris. Bạn nói đúng, tôi đã chỉnh sửa mã thành pdfWriter.CloseStream = false;
Geoff

1
Có @Geoff stream.Possition = 0; là cần thiết, nếu bạn không viết nó, tại thời điểm mở PDF Acrobat ném một lỗi "File hư hỏng"
Alberto León

3
Không thể chuyển đổi ngầm gõ 'System.Web.Mvc.FileStreamResult' thành 'System.Web.Mvc.FileContentResult'
CountMurphy

64

Tôi đã làm cho nó hoạt động với mã này.

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

Document, PdfWriter và Paragraph không được công nhận. Không gian tên nào sẽ được thêm vào?
michael

9
Tôi hơi lo ngại rằng không có một usingcâu lệnh nào trong bất kỳ ví dụ nào mà tôi có thể tìm thấy ... Nó không cần thiết ở đây sao? Tôi nghĩ rằng bạn có ít nhất 3 đối tượng dùng một lần ...
Kobi

Có, sử dụng câu lệnh là tốt. Nếu đây là một ứng dụng sản xuất với hơn, nói ... ONE người sử dụng nó, điều này có thể gây ra vấn đề ...
vbullinger

7
FileSteamResult sẽ đóng luồng cho bạn. Xem câu trả lời này stackoverflow.com/a/10429907/228770
Ed Spencer

Điều quan trọng là đặt Vị trí = 0. haha. cảm ơn bạn @TonyBorf
ThanhLD

23

Bạn phải chỉ định:

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

Để tệp được mở trực tiếp trong trình duyệt thay vì tải xuống


Cảm ơn bạn! Tôi đã tìm kiếm khắp nơi về cách làm điều này !!
Scottie

17

Nếu bạn trả về một FileResulttừ phương thức hành động của mình và sử dụng File()phương thức mở rộng trên bộ điều khiển, việc thực hiện những gì bạn muốn là khá dễ dàng. Có những ghi đè đối với File()phương thức sẽ lấy nội dung nhị phân của tệp, đường dẫn đến tệp hoặc a Stream.

public FileResult DownloadFile()
{
    return File("path\\to\\pdf.pdf", "application/pdf");
}

11

Tôi đã gặp phải những vấn đề tương tự và tôi đã vấp phải một giải pháp. Tôi sử dụng hai bài viết, một từ đống rằng chương trình phương pháp để trở về để tải về và một một mà chương trình một giải pháp làm việc cho iTextSharp và 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
    // /programming/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");
}

Ví dụ xuất sắc! Đây chính xác là những gì tôi đang tìm kiếm! - Pete -
DigiOz Multimedia

2
Sử dụng? Đóng? Vứt bỏ? Tuôn ra? Ai quan tâm đến việc rò rỉ bộ nhớ?
vbullinger


3

Tôi biết câu hỏi này đã cũ nhưng tôi nghĩ tôi sẽ chia sẻ điều này vì tôi không thể tìm thấy bất kỳ điều gì tương tự.

Tôi muốn tạo các khung nhìn / mô hình của mình như bình thường bằng Razor và để chúng được hiển thị dưới dạng Pdf .

Bằng cách này, tôi có quyền kiểm soát bản trình bày pdf bằng cách sử dụng đầu ra html chuẩn hơn là tìm cách bố trí tài liệu bằng iTextSharp.

Dự án và mã nguồn có sẵn tại đây với hướng dẫn cài đặt nuget:

https://github.com/andyhutch77/MvcRazorToPdf

Install-Package MvcRazorToPdf

3

FileStreamResultchắc chắn hoạt động. Nhưng nếu bạn nhìn vào Microsoft Docs , nó kế thừa từ ActionResult -> FileResult, có một lớp dẫn xuất khác FileContentResult. Nó "gửi nội dung của một tệp nhị phân đến phản hồi". Vì vậy, nếu bạn đã có byte[], bạn chỉ nên sử dụng FileContentResultthay thế.

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

    return new FileContentResult(byteArray, "application/pdf");
}

2

Thông thường bạn sẽ thực hiện một Response.Flush theo sau bởi một Response.Close, nhưng vì một số lý do mà thư viện iTextSharp dường như không thích điều này. Dữ liệu không được thông qua và Adobe cho rằng tệp PDF bị hỏng. Bỏ chức năng Response.Close và xem kết quả của bạn có tốt hơn không:

Response.Clear();
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-disposition", "attachment; filename=file.pdf"); // open in a new window
Response.OutputStream.Write(outStream.GetBuffer(), 0, outStream.GetBuffer().Length);
Response.Flush();

// For some reason, if we close the Response stream, the PDF doesn't make it through
//Response.Close();

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

nếu tên tệp đang được tạo động thì làm thế nào để xác định tên tệp ở đây, nó được tạo thông qua hướng dẫn ở đây.


1

nếu bạn trả về dữ liệu var-binary từ DB để hiển thị PDF trên cửa sổ bật lên hoặc trình duyệt có nghĩa là hãy làm theo mã sau: -

Xem trang:

@using (Html.BeginForm("DisplayPDF", "Scan", FormMethod.Post))
    {
        <a href="javascript:;" onclick="document.forms[0].submit();">View PDF</a>
    }

Bộ điều khiển quét:

public ActionResult DisplayPDF()
        {
            byte[] byteArray = GetPdfFromDB(4);
            MemoryStream pdfStream = new MemoryStream();
            pdfStream.Write(byteArray, 0, byteArray.Length);
            pdfStream.Position = 0;
            return new FileStreamResult(pdfStream, "application/pdf");
        }

        private byte[] GetPdfFromDB(int id)
        {
            #region
            byte[] bytes = { };
            string constr = System.Configuration.ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
            using (SqlConnection con = new SqlConnection(constr))
            {
                using (SqlCommand cmd = new SqlCommand())
                {
                    cmd.CommandText = "SELECT Scan_Pdf_File FROM PWF_InvoiceMain WHERE InvoiceID=@Id and Enabled = 1";
                    cmd.Parameters.AddWithValue("@Id", id);
                    cmd.Connection = con;
                    con.Open();
                    using (SqlDataReader sdr = cmd.ExecuteReader())
                    {
                        if (sdr.HasRows == true)
                        {
                            sdr.Read();
                            bytes = (byte[])sdr["Scan_Pdf_File"];
                        }
                    }
                    con.Close();
                }
            }

            return bytes;
            #endregion
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.