Hoe kan ik de PDF terugzetten naar de browser in MVC?

Ik heb deze democode voor 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();

Hoe zorg ik ervoor dat de controller het pdf-document terugstuurt naar de browser?

BEWERKEN:

Als u deze code uitvoert, wordt Acrobat wel geopend, maar ik krijg de foutmelding “Het bestand is beschadigd en kan niet worden gerepareerd”

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

Enig idee waarom dit niet werkt?


Antwoord 1, autoriteit 100%

Retourneer een FileContentResult. De laatste regel in uw controlleractie zou zoiets zijn als:

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

Als u deze PDF dynamisch genereert, is het wellicht beter om een ​​MemoryStreamte gebruiken en het document in het geheugen aan te maken in plaats van in een bestand op te slaan. De code zou zoiets zijn als:

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

Antwoord 2, autoriteit 52%

Ik heb het werkend gekregen met deze code.

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

Antwoord 3, autoriteit 21%

U moet specificeren:

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

Om het bestand direct te openenin de browser in plaats van te downloaden


Antwoord 4, autoriteit 14%

Als je een FileResultvan je actiemethode retourneert en de extensiemethode File()op de controller gebruikt, is het vrij eenvoudig om te doen wat je wilt. Er zijn overschrijvingen op de methode File()die de binaire inhoud van het bestand, het pad naar het bestand of een Streamoverneemt.

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

Antwoord 5, autoriteit 8%

Ik heb in soortgelijke problemen lopen en ik heb struikelde tegenkwam een ​​oplossing. Ik gebruikte twee posten, een van stapel Hieruit blijkt de methode rendement voor downloaden en ander een die toont een werkoplossing voor iTextSharp en 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
    // https://stackoverflow.com/questions/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");
}

Antwoord 6, Autoriteit 5%

FileStreamResultwerkt zeker. Maar als je kijkt naar de Microsoft Docs , waar het van erft ActionResult -> FileResult, die een afgeleide klasse heeft FileContentResult. It “stuurt de inhoud van een binair bestand naar de reactie”. Dus als u al de byte[], moet je gewoon gebruik maken van FileContentResult.

public ActionResult DisplayPDF()
{
    byte[] byteArray = GetPdfFromWhatever();
    return new FileContentResult(byteArray, "application/pdf");
}

Antwoord 7, Autoriteit 2%

U kunt een aangepaste klasse te maken om het type inhoud te wijzigen en voeg het bestand naar de respons.

http://haacked.com/archive/2008/05/10/writing-a-custom-file-download-action-result-for-asp.net-mvc.aspx


Antwoord 8, Autoriteit 2%

Ik weet dat deze vraag is oud, maar ik dacht dat ik zou dit deel als ik kon niet iets soortgelijks vinden.

Ik wilde mijn views / modellen te maken als normaal met Razor en hebben ze weergegeven als PDF-bestanden .

Op deze manier had ik de controle over de PDF-presentatie met behulp van standaard HTML-uitvoer in plaats van het uitzoeken hoe het document lay-out met behulp van iTextSharp.

Het project en de broncode is beschikbaar hier met Nuget installatie-instructies:

https://github.com/andyhutch77/MvcRazorToPdf

Install-Package MvcRazorToPdf

Antwoord 9, Autoriteit 2%

Normaal gesproken zou je een Response.Flush doen gevolgd door een Response.Close, maar om de een of andere reden lijkt de iTextSharp-bibliotheek dit niet leuk te vinden. De gegevens komen er niet door en Adobe denkt dat de PDF corrupt is. Laat de functie Response.Close weg en kijk of uw resultaten beter zijn:

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

Antwoord 10, autoriteit 2%

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

als de bestandsnaam dynamisch wordt gegenereerd, hoe de bestandsnaam hier te definiëren, wordt deze hier gegenereerd via de guid.


Antwoord 11

als u var-binaire gegevens uit DB retourneert om PDF in pop-up of browser weer te geven, volgt u deze code:-

Bekijk pagina:

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

Scancontroller:

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
        }

Other episodes