等待用户在 Javascript 中完成下载 blob
在 Javascript 中,我创建了许多想要提示用户保存为文件的 blob.目前,我正在使用 URL.createObjectURL
执行此操作,将 URL 放在链接中,并模拟对链接的点击.(当然,我调用 URL.revokeObjectURL
来释放 URL,以便在用户保存后可以丢弃 blob.)我有一个循环贯穿并为我希望用户执行的每个 blob 执行此操作保存.
In Javascript, I'm creating a number of blobs that I want to prompt the user to save as files. At the moment, I'm doing that using URL.createObjectURL
, placing the URL in a link, and simulating a click to the link. (Of course I call URL.revokeObjectURL
to release the URL so the blob can be discarded after the user saves it.) I have a loop that runs through and does this for each blob I want the user to save.
至少在Firefox上,触发链接是一个异步操作;我调用 click()
并在用户选择保存文件的位置之前立即生成其余 blob 的循环继续执行.
At least on Firefox, triggering the link is an asynchronous operation; I call click()
and my loop to generate the rest of the blobs immediately continues execution before the user chooses a location to save the file.
这会带来一些问题,因为每个 blob 都可能有点大,而且可能有很多.我可以很容易地预见到这样一种情况,即没有足够的内存来将它们全部保存在内存中,等待用户一个接一个地保存和释放它们.所以我想生成一个 blob,让用户下载它,然后, 文件已保存(因此有资格被垃圾收集器丢弃),继续生成下一个 blob 并让用户保存它.
This presents a bit of a problem because each blob could be somewhat large, and there could be a lot of them. I can easily foresee a situation where there wouldn't be sufficient memory to hold all of them in memory waiting for the user to save and release them one-by-one. So I'd like to generate one blob, have the user download it, and then, after the file has been saved (and thus is eligible to be discarded by the garbage collector), proceed to generate the next blob and have the user save it.
有没有什么方法可以实现这一点,而不需要用户手动单击另一个按钮或类似的东西来向页面发出他已完成保存文件的信号?
Is there any way to achieve this without requiring the user to manually click another button or some such thing to signal the page that he is done saving the file?
推荐答案
这对我有用.
/**
*
* @param {object} object A File, Blob, or MediaSource object to create an object URL for. https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
* @param {string} filenameWithExtension
*/
function saveObjectToFile (object, filenameWithExtension) {
console.log('saveObjectToFile: object', object, 'filenameWithExtension', filenameWithExtension)
const url = window.URL.createObjectURL(object)
console.log('url', url)
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.target = '_blank'
link.download = filenameWithExtension
console.log('link', link)
document.body.appendChild(link)
link.click()
window.setTimeout(function () {
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
}, 0)
}
/**
* @param {string} path
* @param {object} payload
* @param {string} filenameWithExtension
* @returns {promise}
*/
export async function downloadFileInBackground (path, payload, filenameWithExtension) {
console.log('downloadFileInBackground awaiting fetch...')
const response = await fetch(path, {
method: 'POST',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json'
},
body: payload // body data type must match "Content-Type" header
})
console.log('response', response)
const blob = await response.blob()
saveObjectToFile(blob, filenameWithExtension)
console.log('downloadFileInBackground finished saving blob to file!', filenameWithExtension)
}
我知道其他人也有这个问题:
I know other people have this problem too:
- https://stackoverflow.com/a/55705784/470749
- https://stackoverflow.com/a/37240906/470749
- https://stackoverflow.com/a/30708820/470749
- 等待用户在 Javascript 中完成 blob 下载
- https://stackoverflow.com/a/50698058/470749
附:我很欣赏@sicking 在 https://github.com/whatwg/的想法html/issues/954#issue-144165132.
P.S. I appreciate the idea from @sicking at https://github.com/whatwg/html/issues/954#issue-144165132.
相关文章