Как я могу отозвать URL объекта только после его загрузки?
Я сохраняю файл в JavaScript, используя следующий код:
var a = document.createElement('a');
a.href = URL.createObjectURL(new Blob(['SOME DATA']));
a.download = 'some.dat';
a.click();
Я хочу отозвать URL (используя URL.revokeObjectURL) после загрузки файла. Когда это безопасно?
Могу ли я отозвать его сразу после звонка a.click()
(что, кажется, работает, но я не уверен, что это безопасно)? В a
Слушатель событий щелчка? Есть ли способ заставить прослушиватель событий щелчка запускаться после действия по умолчанию?
2 ответа
После некоторых экспериментов кажется, что и Chrome, и Safari могут нормально загружать файл размером 2 ГБ при отзыве сразу после нажатия элемента. И Firefox смог загрузить файл размером 600 МБ до того, как браузер начал зависать.
Это то, что я использовал для загрузки больших файлов:
const a = document.createElement('a');
const buffer = new ArrayBuffer(2_000_000_000);
const view = new Uint8Array(buffer);
for(let i=0; i<view.length; i++) {
view[i] = 255;
}
a.href = URL.createObjectURL(new Blob([buffer]));
a.download = 'some.dat';
a.click();
URL.revokeObjectURL(a.href);
В спецификации конкретно не упоминается прерывание существующих потоков при отзыве URL-адреса, поэтому теоретически делать это таким образом было бы вполне нормально.
Однако, чтобы быть в безопасности, я бы либо отозвал URL-адрес через несколько секунд, используя
setTimeout()
, или если загрузка инициируется с определенного экрана, вы можете добавить логику для ее отмены, когда пользователь уходит с этого экрана.
Браузеры также автоматически отзывают URL-адреса объектов после закрытия последней страницы вашего домена, поэтому в зависимости от вашей ситуации отказ от отзыва URL-адресов вообще может быть жизнеспособным решением.
a.click()
элемент DOM имитирует щелчок по элементу, а не распространение события click, поэтому он напрямую отправляется в браузер. Я считаю, что было бы немного безопаснее переместить отзыв объекта URL в другой цикл событий, используя таймер:
setTimeout(function() {
URL.revokeObjectURL(a.href);
}, 0);