Вы не можете напрямую вернуть файл для загрузки через вызов AJAX, поэтому альтернативным подходом является использование вызова AJAX для публикации связанных данных на вашем сервере. Затем вы можете использовать код на стороне сервера для создания файла Excel (я бы рекомендовал использовать для этого EPPlus или NPOI, хотя это звучит так, как будто у вас эта часть работает).
ОБНОВЛЕНИЕ Сентябрь 2016 г.
Мой первоначальный ответ (ниже) был старше 3 лет, поэтому я подумал, что обновлю, поскольку я больше не создаю файлы на сервере при загрузке файлов через AJAX, однако я оставил исходный ответ, поскольку он может быть полезен, все еще в зависимости от ваши конкретные требования.
Распространенный сценарий в моих приложениях MVC - создание отчетов через веб-страницу, на которой есть некоторые параметры отчета, настроенные пользователем (диапазоны дат, фильтры и т. Д.). Когда пользователь указал параметры, которые они отправляют на сервер, создается отчет (например, файл Excel в качестве выходных данных), а затем я сохраняю полученный файл в виде массива байтов в TempData
корзине с уникальной ссылкой. Эта ссылка возвращается как результат Json в мою функцию AJAX, которая впоследствии перенаправляет на отдельное действие контроллера для извлечения данных TempData
и загрузки в браузер конечных пользователей.
Чтобы представить это более подробно, предположим, что у вас есть представление MVC, которое имеет форму, привязанную к классу модели, позвольте вызвать модель ReportVM
.
Во-первых, для получения опубликованной модели требуется действие контроллера, например:
public ActionResult PostReportPartial(ReportVM model){
ExcelPackage workbook = new ExcelPackage();
string handle = Guid.NewGuid().ToString();
using(MemoryStream memoryStream = new MemoryStream()){
workbook.SaveAs(memoryStream);
memoryStream.Position = 0;
TempData[handle] = memoryStream.ToArray();
}
return new JsonResult() {
Data = new { FileGuid = handle, FileName = "TestReportOutput.xlsx" }
};
}
Вызов AJAX, который отправляет мою форму MVC указанному выше контроллеру и получает ответ, выглядит следующим образом:
$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{
return new EmptyResult();
}
}
Еще одно изменение, которое при необходимости может быть легко выполнено, - это передача MIME-типа файла в качестве третьего параметра, чтобы одно действие контроллера могло правильно обслуживать различные форматы выходных файлов.
Это устраняет необходимость в каких-либо физических файлах для создания и хранения на сервере, поэтому никаких дополнительных процедур не требуется, и, опять же, это легко для конечного пользователя.
Обратите внимание: преимущество использования TempData
вместо Session
заключается в том, что после TempData
считывания данные очищаются, поэтому использование памяти будет более эффективным при большом объеме файловых запросов. См. Рекомендации по использованию 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.
- Параметр data содержит данные json, которые будут извлечены из формы.
- returnValue будет именем вашего вновь созданного файла Excel.
- Команда window.location перенаправляет на метод Controller / Action, который фактически возвращает ваш файл для загрузки.
Примерный метод контроллера для действия Download:
[HttpGet]
public virtual ActionResult Download(string file)
{
string fullPath = Path.Combine(Server.MapPath("~/MyFiles"), file);
return File(fullPath, "application/vnd.ms-excel", file);
}