Подождите, пока пользователь закончит загрузку BLOB-объекта в Javascript
В Javascript я создаю несколько больших двоичных объектов, которые я хочу предложить пользователю сохранить в виде файлов. На данный момент я делаю это с помощью URL.createObjectURL
размещение URL в ссылке и симуляция клика по ссылке. (Конечно звоню URL.revokeObjectURL
освободить URL, чтобы можно было удалить большой двоичный объект после того, как пользователь его сохранит.) У меня есть цикл, который выполняется и делает это для каждого большого двоичного объекта, который я хочу сохранить.
По крайней мере, в Firefox запуск ссылки является асинхронной операцией; Я звоню click()
и мой цикл для генерации остальных блобов немедленно продолжает выполнение, прежде чем пользователь выберет место для сохранения файла.
Это представляет собой небольшую проблему, потому что каждый шарик может быть несколько большим, и их может быть много. Я легко могу предвидеть ситуацию, когда не хватит памяти, чтобы держать их все в памяти, ожидая, пока пользователь сохранит и выпустит их один за другим. Поэтому я хотел бы сгенерировать один большой двоичный объект, попросить пользователя загрузить его, а затем, после того, как файл будет сохранен (и, следовательно, может быть удален сборщиком мусора), перейти к созданию следующего большого двоичного объекта и сохранить сохранение пользователем. Это.
Есть ли способ достичь этого, не требуя от пользователя ручного нажатия другой кнопки или чего-то такого, что сигнализирует странице о том, что он завершил сохранение файла?
1 ответ
Это то, что сработало для меня.
/**
*
* @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)
}
Я знаю, что у других людей тоже есть эта проблема:
- /questions/23913486/chrome-pdf-viewer-ne-mozhet-zagruzit-fajl/49442306#49442306
- /questions/2961334/kak-ya-mogu-otozvat-url-obekta-tolko-posle-ego-zagruzki/2961340#2961340
- /questions/45427909/zagruzka-blob-obekta-createobjecturl-ne-rabotaet-v-firefox-no-rabotaet-pri-otladke/45427920#45427920
- Подождите, пока пользователь завершит загрузку большого двоичного объекта в Javascript.
- /questions/17186213/osvobozhdenie-pamyati-ot-sozdaniya-bloba-url-obekta-pri-zapisi-fajla-na-disk-klienta/17186221#17186221
PS Я ценю идею от @sicking на https://github.com/whatwg/html/issues/954#issue-144165132 .