當強製通過window.location下載時,如何在JavaScript中設置blob文件的名稱?
function newFile(data) {
var json = JSON.stringify(data);
var blob = new Blob([json], {type: "octet/stream"});
var url = window.URL.createObjectURL(blob);
window.location.assign(url);
}
運行上麵的代碼會立即下載文件而不會刷新頁麵,文件名類似如下所示的隨機字符串:
bfefe410-8d9c-4883-86c5-d76c50a24a1d
那麽我想將文件名設置為my-download.json,該怎麽做?
最佳解決思路
我知道的唯一方法是FileSaver.js使用的技巧:
- 創建隱藏的
<a>
標記。 - 將其
href
屬性設置為blob的URL。 - 將其
download
屬性設置為文件名。 - 單擊
<a>
標記。
這是一個簡化的例子(jsfiddle):
var saveData = (function () {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (data, fileName) {
var json = JSON.stringify(data),
blob = new Blob([json], {type: "octet/stream"}),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
}());
var data = { x: 42, s: "hello, world", d: new Date() },
fileName = "my-download.json";
saveData(data, fileName);
我寫這個例子隻是為了說明這個想法,在生產代碼中使用FileSaver.js代替。
注意
- 較舊的瀏覽器不支持”download”屬性,因為它是HTML5的一部分。
- 瀏覽器認為某些文件格式不安全,會下載失敗。保存帶有txt擴展名的JSON文件對我有用。
次佳解決思路
我擴展了上文中的答案,可支持Internet Explorer(大多數現代版本),並且使用了jQuery整理代碼:
$(document).ready(function() {
saveFile("Example.txt", "data:attachment/text", "Hello, world.");
});
function saveFile (name, type, data) {
if (data != null && navigator.msSaveBlob)
return navigator.msSaveBlob(new Blob([data], { type: type }), name);
var a = $("<a style='display: none;'/>");
var url = window.URL.createObjectURL(new Blob([data], {type: type}));
a.attr("href", url);
a.attr("download", name);
$("body").append(a);
a[0].click();
window.URL.revokeObjectURL(url);
a.remove();
}
第三種解決思路
與上述解決方案相同的原理。但我遇到了Firefox 52.0(32位)的問題,其中大文件(> 40 MBytes)在隨機位置被截斷。 Re-scheduling調用 revokeObjectUrl()解決了這個問題。
function saveFile(blob, filename) {
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, filename);
} else {
const a = document.createElement('a');
document.body.appendChild(a);
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = filename;
a.click();
setTimeout(() => {
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}, 0)
}
}
第四種思路
我遇到了同樣的問題,我的解決方案。
function newFile(data, fileName) {
var json = JSON.stringify(data);
//IE11 support
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
let blob = new Blob([json], {type: "application/json"});
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {// other browsers
let file = new File([json], fileName, {type: "application/json"});
let exportUrl = URL.createObjectURL(file);
window.location.assign(exportUrl);
URL.revokeObjectURL(exportUrl);
}
}
第五種思路
saveFileOnUserDevice = function(file){ // content: blob, name: string
if(navigator.msSaveBlob){ // For ie and Edge
return navigator.msSaveBlob(file.content, file.name);
}
else{
let link = document.createElement('a');
link.href = window.URL.createObjectURL(file.content);
link.download = file.name;
document.body.appendChild(link);
link.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));
link.remove();
window.URL.revokeObjectURL(link.href);
}
}
參考資料