MVC 컨트롤러에서 다운로드 할 파일을 표시하려면 어떻게해야합니까?


109

WebForms에서는 일반적으로 브라우저가 PDF와 같은 임의의 파일 유형과 파일 이름이있는 "파일 다운로드"팝업을 표시 할 수 있도록 다음과 같은 코드를 사용합니다.

Response.Clear()
Response.ClearHeaders()
''# Send the file to the output stream
Response.Buffer = True

Response.AddHeader("Content-Length", pdfData.Length.ToString())
Response.AddHeader("Content-Disposition", "attachment; filename= " & Server.HtmlEncode(filename))

''# Set the output stream to the correct content type (PDF).
Response.ContentType = "application/pdf"

''# Output the file
Response.BinaryWrite(pdfData)

''# Flushing the Response to display the serialized data
''# to the client browser.
Response.Flush()
Response.End()

ASP.NET MVC에서 동일한 작업을 어떻게 수행합니까?

답변:


181

반품 FileResult또는 FileStreamResult파일이 존재하거나 즉석에서 그것을 만들 여부에 따라 액션에서.

public ActionResult GetPdf(string filename)
{
    return File(filename, "application/pdf", Server.UrlEncode(filename));
}

14
이것은 ASP.NET MVC가 멋진 이유를 보여주는 좋은 예입니다. 이전에 9 줄의 혼란스러워 보이는 코드에서했던 작업을 한 줄로 수행 할 수 있습니다. 훨씬 쉽습니다!
Jon Kruger

감사합니다 tvanfosson, 나는 이것을하기위한 최선의 해결책을 찾았고 이것은 훌륭하다.
Mark Kadlec

1
파일 이름에 파일 확장자가 필요합니다. 그렇지 않으면 파일 이름과 콘텐츠 유형을 완전히 무시하고 파일을 브라우저로 스트리밍합니다. 또한 브라우저가 다운로드를 강제 할 때 콘텐츠 유형 (예 : 옥텟 스트림)을 인식하지 못하고 확장자가 전혀없는 경우 웹 페이지 이름 만 사용합니다.
RichC 2013 년

62

브라우저의 PDF 플러그인에서 처리하는 대신 PDF 파일을 강제로 다운로드하려면 :

public ActionResult DownloadPDF()
{
    return File("~/Content/MyFile.pdf", "application/pdf", "MyRenamedFile.pdf");
}

브라우저가 기본 동작 (플러그인 또는 다운로드)으로 처리하도록하려면 두 개의 매개 변수를 보내면됩니다.

public ActionResult DownloadPDF()
{
    return File("~/Content/MyFile.pdf", "application/pdf");
}

브라우저 대화 상자에서 파일의 이름을 지정하려면 세 번째 매개 변수를 사용해야합니다.

업데이트 : Charlino가 맞습니다. 세 번째 매개 변수 (다운로드 파일 이름)를 전달할 때 Content-Disposition: attachment;Http 응답 헤더에 추가됩니다. 내 솔루션은 application\force-downloadmime-type 으로 전송 하는 것이었지만 다운로드 파일 이름에 문제가 발생하므로 좋은 파일 이름을 전송하려면 세 번째 매개 변수가 필요하므로 강제로 다운로드 할 필요가 없습니다 .


6
기술적으로 그것은 일어나고있는 것이 아닙니다. 기술적으로 세 번째 매개 변수를 추가하면 MVC 프레임 워크가 헤더를 추가합니다 content-disposition: attachment; filename=MyRenamedFile.pdf. 이것이 다운로드를 강제하는 것입니다. MIME 유형을 다시 application/pdf.
Charlino

2
Charlino에게 감사합니다. 세 번째 매개 변수가 그렇게한다는 것을 깨닫지 못했습니다. 파일 이름을 변경하는 것이라고 생각했습니다.
guzart

2
답을 업데이트하고 세 번째 매개 변수 + Content-Disposition: attachment;관계를 설명하는 +1 .
Charlino

7

Razor 또는 컨트롤러에서 동일한 작업을 수행 할 수 있습니다.

@{
    //do this on the top most of your View, immediately after `using` statement
    Response.ContentType = "application/pdf";
    Response.AddHeader("Content-Disposition", "attachment; filename=receipt.pdf");
}

또는 컨트롤러에서 ..

public ActionResult Receipt() {
    Response.ContentType = "application/pdf";
    Response.AddHeader("Content-Disposition", "attachment; filename=receipt.pdf");

    return View();
}

Chrome과 IE9에서 이것을 시도했는데 둘 다 pdf 파일을 다운로드하고 있습니다.

내 PDF를 생성하기 위해 RazorPDF 를 사용하고 있다고 추가해야합니다 . 여기에 대한 블로그가 있습니다. http://nyveldt.com/blog/post/Introducing-RazorPDF


4

컨트롤러의 File 메서드를 봐야합니다. 이것이 바로 그 목적입니다. ActionResult 대신 FilePathResult를 반환합니다.


3

mgnoonan,

이렇게하면 FileStream을 반환 할 수 있습니다.

/// <summary>
/// Creates a new Excel spreadsheet based on a template using the NPOI library.
/// The template is changed in memory and a copy of it is sent to
/// the user computer through a file stream.
/// </summary>
/// <returns>Excel report</returns>
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult NPOICreate()
{
    try
    {
        // Opening the Excel template...
        FileStream fs =
            new FileStream(Server.MapPath(@"\Content\NPOITemplate.xls"), FileMode.Open, FileAccess.Read);

        // Getting the complete workbook...
        HSSFWorkbook templateWorkbook = new HSSFWorkbook(fs, true);

        // Getting the worksheet by its name...
        HSSFSheet sheet = templateWorkbook.GetSheet("Sheet1");

        // Getting the row... 0 is the first row.
        HSSFRow dataRow = sheet.GetRow(4);

        // Setting the value 77 at row 5 column 1
        dataRow.GetCell(0).SetCellValue(77);

        // Forcing formula recalculation...
        sheet.ForceFormulaRecalculation = true;

        MemoryStream ms = new MemoryStream();

        // Writing the workbook content to the FileStream...
        templateWorkbook.Write(ms);

        TempData["Message"] = "Excel report created successfully!";

        // Sending the server processed data back to the user computer...
        return File(ms.ToArray(), "application/vnd.ms-excel", "NPOINewFile.xls");
    }
    catch(Exception ex)
    {
        TempData["Message"] = "Oops! Something went wrong.";

        return RedirectToAction("NPOI");
    }
}

1

표준 작업 결과 FileContentResult 또는 FileStreamResult를 파일 다운로드에 사용할 수 있지만 재사용 성을 위해 사용자 지정 작업 결과를 만드는 것이 가장 좋은 솔루션 일 수 있습니다.

예를 들어 다운로드를 위해 즉시 Excel 파일로 데이터를 내보내는 사용자 지정 작업 결과를 만들어 보겠습니다.

ExcelResult 클래스는 추상 ActionResult 클래스를 상속하고 ExecuteResult 메서드를 재정의합니다.

IEnumerable 개체에서 DataTable을 생성하기 위해 FastMember 패키지를 사용하고 DataTable에서 Excel 파일을 생성하기 위해 ClosedXML 패키지를 사용하고 있습니다.

public class ExcelResult<T> : ActionResult
{
    private DataTable dataTable;
    private string fileName;

    public ExcelResult(IEnumerable<T> data, string filename, string[] columns)
    {
        this.dataTable = new DataTable();
        using (var reader = ObjectReader.Create(data, columns))
        {
            dataTable.Load(reader);
        }
        this.fileName = filename;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context != null)
        {
            var response = context.HttpContext.Response;
            response.Clear();
            response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            response.AddHeader("content-disposition", string.Format(@"attachment;filename=""{0}""", fileName));
            using (XLWorkbook wb = new XLWorkbook())
            {
                wb.Worksheets.Add(dataTable, "Sheet1");
                using (MemoryStream stream = new MemoryStream())
                {
                    wb.SaveAs(stream);
                    response.BinaryWrite(stream.ToArray());
                }
            }
        }
    }
}

컨트롤러에서 다음과 같이 사용자 지정 ExcelResult 작업 결과를 사용합니다.

[HttpGet]
public async Task<ExcelResult<MyViewModel>> ExportToExcel()
{
    var model = new Models.MyDataModel();
    var items = await model.GetItems();
    string[] columns = new string[] { "Column1", "Column2", "Column3" };
    string filename = "mydata.xlsx";
    return new ExcelResult<MyViewModel>(items, filename, columns);
}

HttpGet을 사용하여 파일을 다운로드하고 있으므로 모델없이 빈 레이아웃과 빈 뷰를 만듭니다.

즉석에서 생성 된 파일을 다운로드하기위한 사용자 지정 작업 결과에 대한 블로그 게시물 :

https://acanozturk.blogspot.com/2019/03/custom-actionresult-for-files-in-aspnet.html


-4

.ashx 파일 유형을 사용하고 동일한 코드를 사용하십시오.

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