AJAX 호출을 통해 다운로드 할 파일을 직접 반환 할 수 없으므로 다른 방법은 AJAX 호출을 사용하여 관련 데이터를 서버에 게시하는 것입니다. 그런 다음 서버 측 코드를 사용하여 Excel 파일을 만들 수 있습니다 (이 부분이 작동하는 것처럼 들리지만 EPPlus 또는 NPOI를 사용하는 것이 좋습니다).
2016 년 9 월 업데이트
내 원래 답변 (아래)은 3 년 이상되었으므로 AJAX를 통해 파일을 다운로드 할 때 더 이상 서버에 파일을 만들지 않기 때문에 업데이트 할 것이라고 생각했지만 여전히 사용에 따라 원래 답변을 남겼습니다. 귀하의 특정 요구 사항.
내 MVC 애플리케이션의 일반적인 시나리오는 사용자가 구성한 보고서 매개 변수 (날짜 범위, 필터 등)가있는 웹 페이지를 통해보고하는 것입니다. 사용자가 서버에 게시하는 매개 변수를 지정하면 보고서가 생성되고 (예 : Excel 파일을 출력으로) 결과 파일을 TempData
고유 한 참조 가있는 버킷에 바이트 배열로 저장합니다 . 이 참조는 TempData
최종 사용자 브라우저 에서 데이터를 추출 하고 다운로드하기 위해 별도의 컨트롤러 작업으로 리디렉션되는 내 AJAX 함수에 Json 결과로 다시 전달됩니다 .
좀 더 자세히 설명하기 위해 Model 클래스에 바인딩 된 폼이있는 MVC 뷰가 있다고 가정하고 Model을 호출 할 수 있습니다 ReportVM
.
첫째, 게시 된 모델을 수신하려면 컨트롤러 작업이 필요합니다. 예는 다음과 같습니다.
public ActionResult PostReportPartial(ReportVM model){
// Validate the Model is correct and contains valid data
// Generate your report output based on the model parameters
// This can be an Excel, PDF, Word file - whatever you need.
// As an example lets assume we've generated an EPPlus ExcelPackage
ExcelPackage workbook = new ExcelPackage();
// Do something to populate your workbook
// Generate a new unique identifier against which the file can be stored
string handle = Guid.NewGuid().ToString();
using(MemoryStream memoryStream = new MemoryStream()){
workbook.SaveAs(memoryStream);
memoryStream.Position = 0;
TempData[handle] = memoryStream.ToArray();
}
// Note we are returning a filename as well as the handle
return new JsonResult() {
Data = new { FileGuid = handle, FileName = "TestReportOutput.xlsx" }
};
}
내 MVC 양식을 위의 컨트롤러에 게시하고 응답을받는 AJAX 호출은 다음과 같습니다.
$ajax({
cache: false,
url: '/Report/PostReportPartial',
data: _form.serialize(),
success: function (data){
var response = JSON.parse(data);
window.location = '/Report/Download?fileGuid=' + response.FileGuid
+ '&filename=' + response.FileName;
}
})
파일 다운로드를 처리하는 컨트롤러 작업 :
[HttpGet]
public virtual ActionResult Download(string fileGuid, string fileName)
{
if(TempData[fileGuid] != null){
byte[] data = TempData[fileGuid] as byte[];
return File(data, "application/vnd.ms-excel", fileName);
}
else{
// Problem - Log the error, generate a blank file,
// redirect to another controller action - whatever fits with your application
return new EmptyResult();
}
}
필요한 경우 쉽게 수용 할 수있는 또 다른 변경 사항은 하나의 컨트롤러 작업이 다양한 출력 파일 형식을 올바르게 제공 할 수 있도록 파일의 MIME 유형을 세 번째 매개 변수로 전달하는 것입니다.
이렇게하면 물리적 파일을 생성하여 서버에 저장할 필요가 없으므로 하우스 키핑 루틴이 필요하지 않으며 최종 사용자에게도 원활하게 제공됩니다.
한 번 읽는 TempData
것보다 사용의 장점은 데이터가 지워 지므로 많은 양의 파일 요청이있는 경우 메모리 사용량 측면에서 더 효율적이라는 것입니다. TempData 모범 사례를 참조하십시오 .Session
TempData
원래 답변
AJAX 호출을 통해 다운로드 할 파일을 직접 반환 할 수 없으므로 다른 방법은 AJAX 호출을 사용하여 관련 데이터를 서버에 게시하는 것입니다. 그런 다음 서버 측 코드를 사용하여 Excel 파일을 만들 수 있습니다 (이 부분이 작동하는 것처럼 들리지만 EPPlus 또는 NPOI를 사용하는 것이 좋습니다).
파일이 서버에 생성되면 AJAX 호출에 대한 반환 값으로 파일 경로 (또는 파일 이름 만)를 다시 전달한 다음 JavaScript window.location
를이 URL 로 설정 하면 브라우저에서 파일을 다운로드하라는 메시지가 표시됩니다.
최종 사용자의 관점에서 파일 다운로드 작업은 요청이 시작된 페이지를 떠나지 않기 때문에 원활합니다.
다음은이를 달성하기위한 ajax 호출의 간단한 인위적인 예입니다.
$.ajax({
type: 'POST',
url: '/Reports/ExportMyData',
data: '{ "dataprop1": "test", "dataprop2" : "test2" }',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (returnValue) {
window.location = '/Reports/Download?file=' + returnValue;
}
});
- url 매개 변수는 코드가 Excel 파일을 생성하는 Controller / Action 메서드입니다.
- 데이터 매개 변수에는 양식에서 추출되는 json 데이터가 포함됩니다.
- returnValue 는 새로 만든 Excel 파일의 파일 이름입니다.
- 에서는 window.location 실제로 다운로드 할 파일을 반환하는 컨트롤러 / 액션 메소드에 명령 리디렉션.
다운로드 작업에 대한 샘플 컨트롤러 방법은 다음과 같습니다.
[HttpGet]
public virtual ActionResult Download(string file)
{
string fullPath = Path.Combine(Server.MapPath("~/MyFiles"), file);
return File(fullPath, "application/vnd.ms-excel", file);
}