128 votes

Comment renvoyer un PDF au navigateur en MVC ?

J'ai ce code de démonstration pour 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();

Comment faire pour que le contrôleur renvoie le document pdf au navigateur ?

EDIT :

L'exécution de ce code ouvre bien Acrobat, mais j'obtiens un message d'erreur "Le fichier est endommagé et n'a pu être réparé".

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

Avez-vous une idée de la raison pour laquelle cela ne fonctionne pas ?

0 votes

1 votes

@mg1075 votre lien est mort

0 votes

133voto

Geoff Points 2586

Retourner un FileContentResult . La dernière ligne de votre action de contrôleur serait quelque chose comme :

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

Si vous générez ce PDF de manière dynamique, il peut être préférable d'utiliser une balise MemoryStream et créer le document en mémoire au lieu de l'enregistrer dans un fichier. Le code serait quelque chose comme :

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

0 votes

@Tony, vous devez d'abord fermer le document et vider le flux.

2 votes

Geoff, j'essaie de réaliser ceci, mais j'ai des problèmes similaires. J'obtiens une erreur au moment de l'exécution "Impossible d'accéder à un flux fermé". Mais si je ne le ferme pas, rien n'est renvoyé.

1 votes

Merci @littlechris. Vous avez raison, j'ai modifié le code pour inclure pdfWriter.CloseStream = false ;

68voto

Tony Borf Points 1950

Je l'ai fait fonctionner avec ce 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");    
}

1 votes

Document, PdfWriter et Paragraph ne sont pas reconnus. Quel espace de nom doit être ajouté ?

9 votes

Je suis un peu préoccupé par le fait qu'il n'y a pas un seul using dans tous les exemples que j'ai pu trouver... N'est-elle pas nécessaire ici ? Je pense que vous avez au moins 3 objets jetables...

0 votes

Oui, les déclarations d'utilisation sont bonnes. Si c'est une application de production avec plus de, disons... UNE personne qui l'utilise, cela peut poser des problèmes...

28voto

Machinegon Points 522

Vous devez spécifier :

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

Pour que le fichier soit ouvert directement dans le navigateur au lieu d'être téléchargé

0 votes

Merci. J'ai cherché partout comment faire ça !

0 votes

Et évidemment, vous pouvez faire return File(yourByteArray, "application/pdf"); si vous avez un tableau d'octets au lieu d'un flux.

18voto

NerdFury Points 9935

Si vous renvoyez un FileResult de votre méthode d'action, et utilisez le File() méthode d'extension sur le contrôleur, faire ce que vous voulez est assez facile. Il existe des surcharges sur la méthode File() qui prendra le contenu binaire du fichier, le chemin d'accès au fichier, ou un fichier Stream .

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

11voto

littlechris Points 1383

J'ai rencontré des problèmes similaires et je suis tombé sur une solution. J'ai utilisé deux postes, l'un provenant de pile qui indique la méthode à retourner pour le téléchargement et un autre un qui montre une solution fonctionnelle pour ItextSharp et 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");
}

0 votes

Excellent exemple ! C'est exactement ce que je cherchais ! -- Pete

2 votes

Utilisations ? Fermer ? Éliminer ? Flush ? Qui se soucie des fuites de mémoire ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X