Почему файлы отличаются при загрузке из ASP.NET (загрузка AJAX с Blob)
Используя MVC 4.0, я использовал следующий код для создания файлов загрузки с сервера из источника ajax (используя последнюю версию Firefox):
Это работает нормально, если выходные данные включают текстовые файлы, такие как CSV или TXT-файлы, однако, когда дело доходит до файлов, таких как zip или xlsx, кажется, что загруженный файл отличается от исходного источника (т. Е. Архив, созданный на сервере, составляет 15 КБ)., но тот, который загружен, является 26K)
Я боролся в течение нескольких дней, могу ли я спросить, должен ли кто-нибудь пролить свет на то, почему это будет работать для файлов csv/text, а не для файлов zip или xlsx?
Большое спасибо
контроллер:
Public Function download(dataIn As myObject) As ActionResult
'some processing
'generated zip files and return with the full path
Dim zipFullPath = generateFiles(dataIn)
Response.Clear()
Response.ContentType = "application/zip"
Response.AddHeader("Content-Disposition", "attachment; filename=Out.zip")
Dim fileLength = New IO.FileInfo(zipFullPath).Length
'fileLength reads about 15K of data
Response.AddHeader("Content-Length", fileLength)
Response.TransmitFile(zipFullPath)
Response.End()
Return View()
End Function
JavaScript:
$.ajax({
type: "POST",
url: "reports/download",
data: jData,
contentType: "application/json; charset=utf-8",
success: function(response, status, xhr) {
// check for a filename
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([response], { type: type });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
//Here is the problem, the original is about 15k,
// but the download file is about 26K
}
} else {
window.location = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
},
error: function (data) {
alert('Error');
}
});
1 ответ
В настоящее время jQuery ajax может обрабатывать только текстовые ответы, поэтому ваши текстовые файлы работают, а ваши двоичные файлы дают сбой.
Чтобы загрузить нетекстовый файл из ajax, используйте объект XMLHttpRequest и укажите, например, responseType blob
или же arraybuffer
,
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200){
...
var blob = this.response; //save the blob as usual
...
}
}
xhr.open('POST', 'reports/download');
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
xhr.responseType = 'blob'; // the response will be a blob and not text
xhr.send(jData);