Как я могу отозвать 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);
Другие вопросы по тегам