MVC'de PDF'yi tarayıcıya nasıl döndürürüm?


120

İTextSharp için bu demo kodum var

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

Denetleyicinin pdf belgesini tarayıcıya döndürmesini nasıl sağlayabilirim?

DÜZENLE:

Bu kodu çalıştırmak Acrobat'ı açıyor ancak "Dosya hasarlı ve onarılamadı" hata mesajı alıyorum

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

Bunun neden işe yaramadığına dair bir fikriniz var mı?



1
@ mg1075 bağlantınız öldü
thecoolmacdude

Yanıtlar:


128

Döndür a FileContentResult. Denetleyici eyleminizdeki son satır şu şekilde olacaktır:

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

Bu PDF'yi dinamik olarak MemoryStreamoluşturuyorsanız, dosyaya kaydetmek yerine a kullanmak ve belgeyi bellekte oluşturmak daha iyi olabilir . Kod şöyle bir şey olacaktır:

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, önce belgeyi kapatmanız ve akışı temizlemeniz gerekir.
Geoff

2
Geoff, bunu başarmaya çalışıyorum ama benzer sorunlar yaşıyorum. Çalışma zamanında "Kapalı bir Akışa erişilemiyor" hatası alıyorum Ancak kapatmazsam hiçbir şey döndürülmez.
littlechris

1
@Littlechris teşekkürler. Haklısınız, pdfWriter.CloseStream = false dahil olmak üzere kodu düzenledim;
Geoff

1
Evet @ Geoff stream.Possition = 0; gereklidir, eğer yazmazsanız, PDF'yi açtığınız anda Acrobat "Dosya hasarlı" hatası
Alberto León

3
'System.Web.Mvc.FileStreamResult' türü örtük olarak 'System.Web.Mvc.FileContentResult' türüne dönüştürülemiyor
CountMurphy

64

Bu kodla çalıştırdım.

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

Belge, PdfWriter ve Paragraf tanınmıyor. Hangi ad alanı eklenecek?
michael

9
Bulabildiğim usinghiçbir örnekte tek bir ifade olmadığı konusunda biraz endişeliyim ... Burada gerek yok mu? Sanırım en az 3 tek kullanımlık nesneniz var ...
Kobi

Evet, ifade kullanmak iyidir. Bu, birden fazla
şeye

7
FileSteamResult akışı sizin için kapatacaktır. Bu yanıta bakın stackoverflow.com/a/10429907/228770
Ed Spencer

Önemli olan Pozisyon = 0. haha. teşekkür ederim @TonyBorf
ThanhLD

23

Şunları belirtmelisiniz:

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

Dosyanın indirilmek yerine doğrudan tarayıcıda açılması için


Teşekkür ederim! Bunu nasıl yapacağımı her yerde arıyordum !!
Scottie

17

FileResultEylem yönteminizden bir döndürürseniz File()ve denetleyicideki genişletme yöntemini kullanırsanız, istediğinizi yapmak oldukça kolaydır. Üzerinde kılmaları var File()dosyası veya karşı, yolunu dosyasının ikili içeriğini alacaktır yöntemle Stream.

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

11

Benzer sorunlarla karşılaştım ve bir çözümle karşılaştım. İki mesajları, bir tane kullanılan yığın yöntemi gösterir indirmek ve başka dönmek için bu bir gösterir itextsharp ve MVC için bir çalışma çözeltisi.

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

Mükemmel Örnek! Bu tam olarak aradığım şeydi! - Pete -
DigiOz Multimedia

2
Usings? Kapat? Elden çıkarmak? Flush? Hafıza sızıntıları kimin umurunda?
vbullinger


3

Bu sorunun eski olduğunu biliyorum ama benzer bir şey bulamadığım için bunu paylaşacağımı düşündüm.

Görünümlerimi / modellerimi Razor kullanarak normal şekilde oluşturmak ve onları Pdf olarak işlemek istedim .

Bu şekilde, iTextSharp kullanarak belgeyi nasıl düzenleyeceğimi bulmak yerine standart html çıktısını kullanarak pdf sunumu üzerinde kontrol sahibi oldum.

Proje ve kaynak kodu, nuget kurulum talimatları ile burada mevcuttur:

https://github.com/andyhutch77/MvcRazorToPdf

Install-Package MvcRazorToPdf

3

FileStreamResultkesinlikle işe yarar. Ancak Microsoft Docs'a bakarsanız ActionResult -> FileResult, başka bir türetilmiş sınıfa sahip olandan miras alır FileContentResult. "İkili dosyanın içeriğini yanıta gönderir". Yani zaten varsa, bunun yerine byte[]kullanmalısınız FileContentResult.

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

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

2

Normalde bir Response.Flush ve ardından bir Response.Close yaparsınız, ancak bazı nedenlerden dolayı iTextSharp kütüphanesi bundan hoşlanmıyor. Veriler bunu başaramaz ve Adobe PDF'nin bozuk olduğunu düşünür. Response.Close işlevini bırakın ve sonuçlarınızın daha iyi olup olmadığına bakın:

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

dosya adı dinamik olarak üretiliyorsa, burada dosya adı nasıl tanımlanır, burada kılavuz aracılığıyla oluşturulmaktadır.


1

Açılır pencerede veya tarayıcıda PDF'yi görüntülemek için DB'den var-ikili verileri döndürürseniz şu kodu izleyin anlamına gelir: -

Sayfaya bak:

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

Tarama denetleyicisi:

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
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.