MVC에서 PDF를 브라우저로 반환하는 방법은 무엇입니까?


120

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

컨트롤러에서 pdf 문서를 브라우저로 반환하려면 어떻게해야합니까?

편집하다:

이 코드를 실행하면 Acrobat이 열리지 만 "파일이 손상되어 복구 할 수 없습니다"라는 오류 메시지가 나타납니다.

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

이것이 작동하지 않는 이유는 무엇입니까?



@ mg1075 귀하의 링크가 죽었
thecoolmacdude

답변:


128

를 반환합니다 FileContentResult. 컨트롤러 작업의 마지막 줄은 다음과 같습니다.

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

이 PDF를 동적으로 생성하는 경우를 사용 MemoryStream하여 파일에 저장하는 대신 메모리에 문서를 만드는 것이 더 나을 수 있습니다 . 코드는 다음과 같습니다.

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, 먼저 문서를 닫고 스트림을 플러시해야합니다.
Geoff

2
Geoff, 나는 이것을 달성하려고 노력하고 있지만 비슷한 문제가 있습니다. 런타임에 "닫힌 스트림에 액세스 할 수 없습니다"라는 오류가 발생하지만 닫지 않으면 아무 것도 반환되지 않습니다.
littlechris 2009

1
감사합니다 @littlechris. 당신 말이 맞습니다. pdfWriter.CloseStream = false를 포함하도록 코드를 편집했습니다.
Geoff

1
예 @Geoff stream.Possition = 0; 작성하지 않으면 PDF를 열 때 Acrobat에서 "파일 손상됨"오류가 발생합니다.
Alberto León

3
암시 적으로 'System.Web.Mvc.FileStreamResult'형식을 'System.Web.Mvc.FileContentResult'로 변환 할 수 없음
CountMurphy

64

이 코드로 작업했습니다.

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 및 Paragraph가 인식되지 않습니다. 추가 할 네임 스페이스는 무엇입니까?
michael

9
내가 using찾을 수있는 어떤 예에서도 단 하나의 진술 이 없다는 것이 조금 걱정됩니다 ... 여기에 필요하지 않습니까? 나는 ... 당신이 적어도 3 일회용 개체가 생각
코비

예, 진술을 사용하는 것이 좋습니다. 한 사람 이상이 사용하는 프로덕션 앱인 경우 문제가 발생할 수 있습니다.
vbullinger

7
FileSteamResult가 스트림을 닫습니다. 이 응답을 참조하십시오 stackoverflow.com/a/10429907/228770
에드 스펜서

중요한 것은 위치 = 0으로 설정하는 것입니다. 하하. 당신에게 @TonyBorf 감사합니다
ThanhLD

23

다음을 지정해야합니다.

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

파일을 다운로드하는 대신 브라우저에서 직접 열 려면


감사합니다! 나는 이것을하는 방법에 대해 모든 곳에서 찾고 있었다!!
Scottie

17

FileResult액션 메서드에서 를 반환 File()하고 컨트롤러 에서 확장 메서드를 사용 하면 원하는 작업을 수행하는 것이 매우 쉽습니다. 온 재정이 있습니다 File()파일, 또는에 경로를 파일의 바이너리 컨텐츠를 취할 것입니다 방법 Stream.

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

11

비슷한 문제가 발생했으며 해결책을 찾았습니다. 나는이 글에서 하나 사용 스택 방법 쇼 다운로드 및 서로를 반환하는 것을 하나 보여 그 ItextSharp과 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");
}

훌륭한 예! 이것이 바로 내가 찾던 것이었다! - 피트 -
DigiOz 멀티미디어

2
사용? 닫기? 폐기 하시겠습니까? 플러시? 누가 메모리 누수를 걱정합니까?
vbullinger 2012 년


3

나는이 질문이 오래되었다는 것을 알고 있지만 비슷한 것을 찾을 수 없기 때문에 이것을 공유 할 것이라고 생각했습니다.

나는 정상으로 내보기 / 모델을 만들고 싶었 면도기를 사용 하고는 한 PDF 파일로 렌더링 .

이렇게하면 iTextSharp를 사용하여 문서를 레이아웃하는 방법을 알아내는 대신 표준 html 출력을 사용하여 pdf 프레젠테이션을 제어 할 수있었습니다.

프로젝트 및 소스 코드는 Nuget 설치 지침과 함께 여기에서 사용할 수 있습니다.

https://github.com/andyhutch77/MvcRazorToPdf

Install-Package MvcRazorToPdf

3

FileStreamResult확실히 작동합니다. 그러나 Microsoft Docs 를 보면 ActionResult -> FileResult다른 파생 클래스가있는 에서 상속됩니다 FileContentResult. "이진 파일의 내용을 응답으로 보냅니다". 따라서 이미을 가지고 있다면 대신 byte[]사용해야 FileContentResult합니다.

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

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

2

일반적으로 Response.Flush 다음에 Response.Close를 수행하지만 어떤 이유로 iTextSharp 라이브러리는 이것을 좋아하지 않는 것 같습니다. 데이터가 통과하지 못하고 Adobe는 PDF가 손상되었다고 생각합니다. Response.Close 함수를 생략하고 결과가 더 나은지 확인하십시오.

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

파일 이름이 동적으로 생성되는 경우 여기에서 파일 이름을 정의하는 방법은 여기에서 guid를 통해 생성됩니다.


1

팝업 또는 브라우저에 PDF를 표시하기 위해 DB에서 var-binary 데이터를 반환하면 다음 코드를 따르십시오.

페이지보기 :

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

스캔 컨트롤러 :

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
        }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.