如何使用 window.fetch 下载文件?
How can I download a file using window.fetch?
如果我想下载一个文件,我应该在下面的then
块中做什么?
function downloadFile(token, fileId) {
let url = `https://www.googleapis.com/drive/v2/files/${fileId}?alt=media`;
return fetch(url, {
method: 'GET',
headers: {
'Authorization': token
}
}).then(...);
}
注意代码在客户端。
我暂时用download.js和blob
解决了这个问题。
let download = require('./download.min');
...
function downloadFile(token, fileId) {
let url = `https://www.googleapis.com/drive/v2/files/${fileId}?alt=media`;
return fetch(url, {
method: 'GET',
headers: {
'Authorization': token
}
}).then(function(resp) {
return resp.blob();
}).then(function(blob) {
download(blob);
});
}
它适用于小文件,但可能不适用于大文件。我想我应该再挖掘 Stream。
编辑:syg 回答更好。只需使用 downloadjs 库。
我提供的答案在 Chrome 上运行良好,但在 Firefox 和 IE 上您需要此代码的一些不同变体。最好使用库。
我遇到了类似的问题(需要通过授权 header 才能下载文件,因此 this 解决方案没有帮助)。
但是根据 this 的回答,您可以使用 createObjectURL
让浏览器保存通过 Fetch 下载的文件 API。
getAuthToken()
.then(token => {
fetch("http://example.com/ExportExcel", {
method: 'GET',
headers: new Headers({
"Authorization": "Bearer " + token
})
})
.then(response => response.blob())
.then(blob => {
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = "filename.xlsx";
document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox
a.click();
a.remove(); //afterwards we remove the element again
});
});
这是一个使用 node-fetch 的示例,供找到此内容的任何人使用。
reportRunner({url, params = {}}) {
let urlWithParams = `${url}?`
Object.keys(params).forEach((key) => urlWithParams += `&${key}=${params[key]}`)
return fetch(urlWithParams)
.then(async res => ({
filename: res.headers.get('content-disposition').split('filename=')[1],
blob: await res.blob()
}))
.catch(this.handleError)
}
function download(dataurl, filename) {
var a = document.createElement("a");
a.href = dataurl;
a.setAttribute("download", filename);
a.click();
return false;
}
download("data:text/html,HelloWorld!", "helloWorld.txt");
或:
function download(url, filename) {
fetch(url).then(function(t) {
return t.blob().then((b)=>{
var a = document.createElement("a");
a.href = URL.createObjectURL(b);
a.setAttribute("download", filename);
a.click();
}
);
});
}
download("https://get.geojs.io/v1/ip/geo.json","geoip.json")
download("data:text/html,HelloWorld!", "helloWorld.txt");
使用下载。这将从 header.
解析文件名
fetch("yourURL", {
method: "POST",
body: JSON.stringify(search),
headers: {
"Content-Type": "application/json; charset=utf-8"
}
})
.then(response => {
if (response.status === 200) {
filename = response.headers.get("content-disposition");
filename = filename.match(/(?<=")(?:\.|[^"\])*(?=")/)[0];
return response.blob();
} else {
return;
}
})
.then(body => {
download(body, filename, "application/octet-stream");
});
};
我试过 window.fetch 但是我的 REACT 应用程序变得很复杂
现在我只需更改 window.location.href 并添加查询参数,例如 jsonwebtoken
和 other stuff
。
///==== client side code =====
var url = new URL(`http://${process.env.REACT_APP_URL}/api/mix-sheets/list`);
url.searchParams.append("interval",data.interval);
url.searchParams.append("jwt",token)
window.location.href=url;
// ===== server side code =====
// on the server i set the content disposition to a file
var list = encodeToCsv(dataToEncode);
res.set({"Content-Disposition":`attachment; filename=\"FileName.csv\"`});
res.status(200).send(list)
最终结果实际上非常好,window 发出请求并下载文件并且没有事件切换将页面移开,就好像 window.location.href
调用一样一个低调的 fetch()
电话。
根据其他一些答案,您绝对可以使用 window.fetch 和 download.js to download a file. However, using window.fetch with blob has the restriction on memory imposed by the browser, and the download.js also has its compatibility restrictions。
如果你需要下载一个大文件,你不想把它放在客户端的内存中给浏览器压力,对吧?相反,您可能更喜欢通过流下载它。在这种情况下,使用 HTML link 下载文件是 best/simplest 方法之一,尤其是通过流下载大文件时。
第一步: 创建 link 元素并设置样式
您可以使 link 不可见但仍可操作。
HTML:
<a href="#" class="download-link" download>Download</a>
CSS:
.download-link {
position: absolute;
top: -9999px;
left: -9999px;
opacity: 0;
}
第二步:设置link的href
,触发click
事件
JavaScript
let url = `https://www.googleapis.com/drive/v2/files/${fileId}?alt=media`;
const downloadLink = document.querySelector('.download-link')
downloadLink.href = url + '&ts=' + new Date().getTime() // Prevent cache
downloadLink.click()
备注:
- 如有必要,您可以动态生成 link 元素。
- 这种方法对于通过流下载在服务器端动态生成的大文件特别有用
这样更短更高效,没有库只获取 API
const url ='http://sample.example.file.doc'
const authHeader ="Bearer 6Q************"
const options = {
headers: {
Authorization: authHeader
}
};
fetch(url, options)
.then( res => res.blob() )
.then( blob => {
var file = window.URL.createObjectURL(blob);
window.location.assign(file);
});
此解决方案不允许您更改下载文件的文件名。文件名将是一个随机的 uuid。
IMO 类似但更清洁、更可靠的解决方案。
关于您的获取功能...
fetch(...)
.then(res =>
{
//you may want to add some validation here
downloadFile(res);
}
)
下载文件函数是...
async function downloadFile(fetchResult) {
var filename = fetchResult.headers.get('content-disposition').split('filename=')[1];
var data = await fetchResult.blob();
// It is necessary to create a new blob object with mime-type explicitly set
// otherwise only Chrome works like it should
const blob = new Blob([data], { type: data.type || 'application/octet-stream' });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE doesn't allow using a blob object directly as link href.
// 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);
return;
}
// Other browsers
// Create a link pointing to the ObjectURL containing the blob
const blobURL = window.URL.createObjectURL(blob);
const tempLink = document.createElement('a');
tempLink.style.display = 'none';
tempLink.href = blobURL;
tempLink.setAttribute('download', filename);
// Safari thinks _blank anchor are pop ups. We only want to set _blank
// target if the browser does not support the HTML5 download attribute.
// This allows you to download files in desktop safari if pop up blocking
// is enabled.
if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank');
}
document.body.appendChild(tempLink);
tempLink.click();
document.body.removeChild(tempLink);
setTimeout(() => {
// For Firefox it is necessary to delay revoking the ObjectURL
window.URL.revokeObjectURL(blobURL);
}, 100);
}
(下载文件函数来源:https://gist.github.com/davalapar/d0a5ba7cce4bc599f54800da22926da2)
如果我想下载一个文件,我应该在下面的then
块中做什么?
function downloadFile(token, fileId) {
let url = `https://www.googleapis.com/drive/v2/files/${fileId}?alt=media`;
return fetch(url, {
method: 'GET',
headers: {
'Authorization': token
}
}).then(...);
}
注意代码在客户端。
我暂时用download.js和blob
解决了这个问题。
let download = require('./download.min');
...
function downloadFile(token, fileId) {
let url = `https://www.googleapis.com/drive/v2/files/${fileId}?alt=media`;
return fetch(url, {
method: 'GET',
headers: {
'Authorization': token
}
}).then(function(resp) {
return resp.blob();
}).then(function(blob) {
download(blob);
});
}
它适用于小文件,但可能不适用于大文件。我想我应该再挖掘 Stream。
编辑:syg 回答更好。只需使用 downloadjs 库。
我提供的答案在 Chrome 上运行良好,但在 Firefox 和 IE 上您需要此代码的一些不同变体。最好使用库。
我遇到了类似的问题(需要通过授权 header 才能下载文件,因此 this 解决方案没有帮助)。
但是根据 this 的回答,您可以使用 createObjectURL
让浏览器保存通过 Fetch 下载的文件 API。
getAuthToken()
.then(token => {
fetch("http://example.com/ExportExcel", {
method: 'GET',
headers: new Headers({
"Authorization": "Bearer " + token
})
})
.then(response => response.blob())
.then(blob => {
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = "filename.xlsx";
document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox
a.click();
a.remove(); //afterwards we remove the element again
});
});
这是一个使用 node-fetch 的示例,供找到此内容的任何人使用。
reportRunner({url, params = {}}) {
let urlWithParams = `${url}?`
Object.keys(params).forEach((key) => urlWithParams += `&${key}=${params[key]}`)
return fetch(urlWithParams)
.then(async res => ({
filename: res.headers.get('content-disposition').split('filename=')[1],
blob: await res.blob()
}))
.catch(this.handleError)
}
function download(dataurl, filename) {
var a = document.createElement("a");
a.href = dataurl;
a.setAttribute("download", filename);
a.click();
return false;
}
download("data:text/html,HelloWorld!", "helloWorld.txt");
或:
function download(url, filename) {
fetch(url).then(function(t) {
return t.blob().then((b)=>{
var a = document.createElement("a");
a.href = URL.createObjectURL(b);
a.setAttribute("download", filename);
a.click();
}
);
});
}
download("https://get.geojs.io/v1/ip/geo.json","geoip.json")
download("data:text/html,HelloWorld!", "helloWorld.txt");
使用下载。这将从 header.
解析文件名fetch("yourURL", {
method: "POST",
body: JSON.stringify(search),
headers: {
"Content-Type": "application/json; charset=utf-8"
}
})
.then(response => {
if (response.status === 200) {
filename = response.headers.get("content-disposition");
filename = filename.match(/(?<=")(?:\.|[^"\])*(?=")/)[0];
return response.blob();
} else {
return;
}
})
.then(body => {
download(body, filename, "application/octet-stream");
});
};
我试过 window.fetch 但是我的 REACT 应用程序变得很复杂
现在我只需更改 window.location.href 并添加查询参数,例如 jsonwebtoken
和 other stuff
。
///==== client side code =====
var url = new URL(`http://${process.env.REACT_APP_URL}/api/mix-sheets/list`);
url.searchParams.append("interval",data.interval);
url.searchParams.append("jwt",token)
window.location.href=url;
// ===== server side code =====
// on the server i set the content disposition to a file
var list = encodeToCsv(dataToEncode);
res.set({"Content-Disposition":`attachment; filename=\"FileName.csv\"`});
res.status(200).send(list)
最终结果实际上非常好,window 发出请求并下载文件并且没有事件切换将页面移开,就好像 window.location.href
调用一样一个低调的 fetch()
电话。
根据其他一些答案,您绝对可以使用 window.fetch 和 download.js to download a file. However, using window.fetch with blob has the restriction on memory imposed by the browser, and the download.js also has its compatibility restrictions。
如果你需要下载一个大文件,你不想把它放在客户端的内存中给浏览器压力,对吧?相反,您可能更喜欢通过流下载它。在这种情况下,使用 HTML link 下载文件是 best/simplest 方法之一,尤其是通过流下载大文件时。
第一步: 创建 link 元素并设置样式
您可以使 link 不可见但仍可操作。
HTML:
<a href="#" class="download-link" download>Download</a>
CSS:
.download-link {
position: absolute;
top: -9999px;
left: -9999px;
opacity: 0;
}
第二步:设置link的href
,触发click
事件
JavaScript
let url = `https://www.googleapis.com/drive/v2/files/${fileId}?alt=media`;
const downloadLink = document.querySelector('.download-link')
downloadLink.href = url + '&ts=' + new Date().getTime() // Prevent cache
downloadLink.click()
备注:
- 如有必要,您可以动态生成 link 元素。
- 这种方法对于通过流下载在服务器端动态生成的大文件特别有用
这样更短更高效,没有库只获取 API
const url ='http://sample.example.file.doc'
const authHeader ="Bearer 6Q************"
const options = {
headers: {
Authorization: authHeader
}
};
fetch(url, options)
.then( res => res.blob() )
.then( blob => {
var file = window.URL.createObjectURL(blob);
window.location.assign(file);
});
此解决方案不允许您更改下载文件的文件名。文件名将是一个随机的 uuid。
IMO 类似但更清洁、更可靠的解决方案。
关于您的获取功能...
fetch(...)
.then(res =>
{
//you may want to add some validation here
downloadFile(res);
}
)
下载文件函数是...
async function downloadFile(fetchResult) {
var filename = fetchResult.headers.get('content-disposition').split('filename=')[1];
var data = await fetchResult.blob();
// It is necessary to create a new blob object with mime-type explicitly set
// otherwise only Chrome works like it should
const blob = new Blob([data], { type: data.type || 'application/octet-stream' });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE doesn't allow using a blob object directly as link href.
// 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);
return;
}
// Other browsers
// Create a link pointing to the ObjectURL containing the blob
const blobURL = window.URL.createObjectURL(blob);
const tempLink = document.createElement('a');
tempLink.style.display = 'none';
tempLink.href = blobURL;
tempLink.setAttribute('download', filename);
// Safari thinks _blank anchor are pop ups. We only want to set _blank
// target if the browser does not support the HTML5 download attribute.
// This allows you to download files in desktop safari if pop up blocking
// is enabled.
if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank');
}
document.body.appendChild(tempLink);
tempLink.click();
document.body.removeChild(tempLink);
setTimeout(() => {
// For Firefox it is necessary to delay revoking the ObjectURL
window.URL.revokeObjectURL(blobURL);
}, 100);
}
(下载文件函数来源:https://gist.github.com/davalapar/d0a5ba7cce4bc599f54800da22926da2)