Hỗ trợ tải xuống các tệp nhị phân trong việc sử dụng ajax không phải là tuyệt vời, nó vẫn đang được phát triển rất nhiều dưới dạng bản nháp đang hoạt động .
Phương pháp tải xuống đơn giản:
Bạn có thể yêu cầu trình duyệt tải xuống tệp được yêu cầu chỉ bằng cách sử dụng mã bên dưới và điều này được hỗ trợ trong tất cả các trình duyệt và rõ ràng sẽ kích hoạt yêu cầu WebApi giống như vậy.
$scope.downloadFile = function(downloadPath) {
window.open(downloadPath, '_blank', '');
}
Phương pháp tải xuống nhị phân Ajax:
Sử dụng ajax để tải xuống tệp nhị phân có thể được thực hiện trong một số trình duyệt và dưới đây là một triển khai sẽ hoạt động theo các hương vị mới nhất của Chrome, Internet Explorer, FireFox và Safari.
Nó sử dụng một arraybuffer
loại phản hồi, sau đó được chuyển đổi thành JavaScript blob
, sau đó được trình bày để lưu bằng saveBlob
phương thức - mặc dù điều này hiện chỉ có trong Internet Explorer - hoặc biến thành URL dữ liệu blob được trình duyệt mở ra, kích hoạt hộp thoại tải xuống nếu loại mime được hỗ trợ để xem trong trình duyệt.
Hỗ trợ Internet Explorer 11 (Đã sửa)
Lưu ý: Internet Explorer 11 không thích sử dụng msSaveBlob
chức năng nếu nó đã được đặt bí danh - có lẽ là một tính năng bảo mật, nhưng nhiều khả năng là một lỗ hổng, Vì vậy, việc sử dụng var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc.
để xác định saveBlob
hỗ trợ có sẵn đã gây ra ngoại lệ; do đó tại sao mã dưới đây bây giờ kiểm tra navigator.msSaveBlob
riêng. Cảm ơn? Microsoft
// Based on an implementation here: web.student.tuwien.ac.at/~e0427417/jsdownload.html
$scope.downloadFile = function(httpPath) {
// Use an arraybuffer
$http.get(httpPath, { responseType: 'arraybuffer' })
.success( function(data, status, headers) {
var octetStreamMime = 'application/octet-stream';
var success = false;
// Get the headers
headers = headers();
// Get the filename from the x-filename header or default to "download.bin"
var filename = headers['x-filename'] || 'download.bin';
// Determine the content type from the header or default to "application/octet-stream"
var contentType = headers['content-type'] || octetStreamMime;
try
{
// Try using msSaveBlob if supported
console.log("Trying saveBlob method ...");
var blob = new Blob([data], { type: contentType });
if(navigator.msSaveBlob)
navigator.msSaveBlob(blob, filename);
else {
// Try using other saveBlob implementations, if available
var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
if(saveBlob === undefined) throw "Not supported";
saveBlob(blob, filename);
}
console.log("saveBlob succeeded");
success = true;
} catch(ex)
{
console.log("saveBlob method failed with the following exception:");
console.log(ex);
}
if(!success)
{
// Get the blob url creator
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
if(urlCreator)
{
// Try to use a download link
var link = document.createElement('a');
if('download' in link)
{
// Try to simulate a click
try
{
// Prepare a blob URL
console.log("Trying download link method with simulated click ...");
var blob = new Blob([data], { type: contentType });
var url = urlCreator.createObjectURL(blob);
link.setAttribute('href', url);
// Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
link.setAttribute("download", filename);
// Simulate clicking the download link
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
console.log("Download link method with simulated click succeeded");
success = true;
} catch(ex) {
console.log("Download link method with simulated click failed with the following exception:");
console.log(ex);
}
}
if(!success)
{
// Fallback to window.location method
try
{
// Prepare a blob URL
// Use application/octet-stream when using window.location to force download
console.log("Trying download link method with window.location ...");
var blob = new Blob([data], { type: octetStreamMime });
var url = urlCreator.createObjectURL(blob);
window.location = url;
console.log("Download link method with window.location succeeded");
success = true;
} catch(ex) {
console.log("Download link method with window.location failed with the following exception:");
console.log(ex);
}
}
}
}
if(!success)
{
// Fallback to window.open method
console.log("No methods worked for saving the arraybuffer, using last resort window.open");
window.open(httpPath, '_blank', '');
}
})
.error(function(data, status) {
console.log("Request failed with status: " + status);
// Optionally write the error out to scope
$scope.errorDetails = "Request failed with status: " + status;
});
};
Sử dụng:
var downloadPath = "/files/instructions.pdf";
$scope.downloadFile(downloadPath);
Ghi chú:
Bạn nên sửa đổi phương thức WebApi của mình để trả về các tiêu đề sau:
Tôi đã sử dụng x-filename
tiêu đề để gửi tên tệp. Đây là một tiêu đề tùy chỉnh để thuận tiện, tuy nhiên bạn có thể trích xuất tên tệp từ content-disposition
tiêu đề bằng các biểu thức thông thường.
Bạn cũng nên đặt content-type
tiêu đề mime cho phản hồi của mình, để trình duyệt biết định dạng dữ liệu.
Tôi hi vọng cái này giúp được.