Nie można bezpośrednio zwrócić pliku do pobrania za pośrednictwem wywołania AJAX, więc alternatywnym podejściem jest użycie wywołania AJAX, aby opublikować powiązane dane na serwerze. Następnie możesz użyć kodu po stronie serwera, aby utworzyć plik Excel (polecam używanie EPPlus lub NPOI, chociaż brzmi to tak, jakby działała ta część).
UPDATE September 2016
Mój oryginalny odpowiedzi (poniżej) był ponad 3 lat, więc myślałem, że chciałbym aktualizować jak już nie tworzyć plików na serwerze, podczas pobierania plików za pośrednictwem AJAX jednak zostawiłem oryginalną odpowiedź jak może być nadal przydatny w zależności od twoich konkretnych wymagań.
Typowym scenariuszem w moich aplikacjach MVC jest raportowanie za pośrednictwem strony internetowej, która ma niektóre skonfigurowane przez użytkownika parametry raportu (zakresy dat, filtry itp.). Gdy użytkownik określi parametry, które przesyłają na serwer, generowany jest raport (np. Jako plik wyjściowy Excela), a następnie przechowuję wynikowy plik jako tablicę bajtów w wiadrze TempData
z unikalnym odniesieniem. To odwołanie jest przekazywane jako wynik Json do mojej funkcji AJAX, która następnie przekierowuje do oddzielnego działania kontrolera, aby wyodrębnić dane z TempData
i pobrać do przeglądarki użytkowników końcowych.
Aby uzyskać więcej szczegółów, zakładając, że masz widok MVC, który ma formularz powiązany z klasą Model, możesz zadzwonić do Modelu ReportVM
.
pierwsze, wymagana jest akcja kontroler otrzymywać zamieszczonych modelu, przykładem może być:
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" }
};
}
wywołania AJAX, że posty mojego formularza MVC do powyższego sterownika i odbiera odpowiedź wygląda następująco:
$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;
}
})
akcja kontroler do obsługi pobierania pliku:
[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();
}
}
Inną inną zmianą, którą można łatwo zastosować, jeśli jest to wymagane, jest przekazanie typu MIME pliku jako trzeciego parametru, aby działanie jednego kontrolera mogło poprawnie obsługiwać różne formaty plików wyjściowych.
Dzięki temu nie trzeba tworzyć żadnych plików fizycznych na serwerze, więc nie trzeba wykonywać żadnych procedur porządkowych, co po raz kolejny jest bezproblemowe dla użytkownika końcowego.
Uwaga, zaletą korzystania TempData
zamiast Session
jest to, że raz TempData
są odczytywane dane są usuwane tak będzie bardziej wydajny pod względem zużycia pamięci, jeśli masz dużą ilość wniosków plików. Zobacz TempData Best Practice.
ORIGINAL Answer
Nie można bezpośrednio zwrócić plik do pobrania za pośrednictwem wywołania AJAX Więc Alternatywnym podejściem jest użycie wywołanie AJAX aby umieścić odpowiednie dane do serwera. Następnie możesz użyć kodu po stronie serwera, aby utworzyć plik Excel (polecam używanie EPPlus lub NPOI, chociaż brzmi to tak, jakby działała ta część).
Po utworzeniu pliku na serwerze należy przekazać ścieżkę do pliku (lub tylko nazwę pliku) jako wartość zwracaną do wywołania AJAX, a następnie ustawić kod JavaScript window.location
na ten adres URL, który będzie monitował przeglądarkę do pobrania plik.
Z punktu widzenia użytkowników końcowych operacja pobierania plików jest bezproblemowa, ponieważ nigdy nie opuszczają strony, z której pochodzi żądanie.
Poniżej znajduje się prosty wymyślony przykład wywołania AJAX do osiągnięcia tego celu:
$.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 parametrem jest metoda Controller/Action gdzie Twój kod utworzy plik Excela.
- Parametr data zawiera dane json, które zostałyby wyodrębnione z formularza.
- returnValue będzie nazwą pliku nowo utworzonego pliku Excel.
- Polecenie window.location powoduje przekierowanie do metody Controller/Action, która faktycznie zwraca plik do pobrania.
Próbka metoda kontroler dla działania Pobrać byłoby:
[HttpGet]
public virtual ActionResult Download(string file)
{
string fullPath = Path.Combine(Server.MapPath("~/MyFiles"), file);
return File(fullPath, "application/vnd.ms-excel", file);
}
To wygląda jak duży potencjał możliwości, ale zanim pójdę do przodu z nim, są tam żadnych innych alternatyw, które nie dotyczą tworzenia pliku na na początku serwer? – Valuk
Nie jestem tego świadomy - to podejście wielokrotnie stosowałem z powodzeniem. Z punktu widzenia użytkowników jest to płynne, jedyną rzeczą, na którą należy zwrócić uwagę, jest to, że będziesz potrzebował procedury porządkowej, aby uporządkować pliki, które są tworzone, ponieważ będą się montować w miarę upływu czasu. – CSL
http://johnculviner.com/jquery-file-download-plugin-for-ajax-like-feature-rich-file-downloads/ –