2016-08-31 3 views
7

У меня есть объект XHR, который загружает 1GB-файл.Большой файл blob в Javascript

function getFile(callback) 
{ 
    var xhr = new XMLHttpRequest(); 
    xhr.onload = function() { 
     if (xhr.status == 200) { 
      callback.apply(xhr); 
     }else{ 
      console.log("Request error: " + xhr.statusText); 
     } 
    }; 

    xhr.open('GET', 'download', true); 
    xhr.onprogress = updateProgress; 
    xhr.responseType = "arraybuffer"; 
    xhr.send(); 
} 

Но API Файл не может загрузить все, что в памяти даже от рабочего он выбрасывает из памяти ...

btn.addEventListener('click', function() { 
    getFile(function() { 
     var worker = new Worker("js/saving.worker.js"); 
     worker.onmessage = function(e) { 
      saveAs(e.data); // FileSaver.js it creates URL from blob... but its too large 
     }; 

     worker.postMessage(this.response); 
    }); 
}); 

Web Worker

onmessage = function (e) { 
    var view = new DataView(e.data, 0); 
    var file = new File([view], 'file.zip', {type: "application/zip"}); 
    postMessage('file'); 
}; 

Я m не пытается сжать файл, этот файл уже сжат с сервера.

Я думал, что хранить его первым на IndexedDB, но я я буду загружать блоб или файл в любом случае, даже если я сделать запрос байтами диапазона, рано или поздно мне придется построить этот гигантский сгусток ..

Я хочу создать blob: url и отправить его пользователю после загрузки браузером

Я использую API FileSystem для Google Chrome, но я хочу сделать что-то для firefox, я заглянул в File Handle Api, но ничего ...

Должен ли я создать расширение для firefox, чтобы сделать то же самое, что и FileSystem для google chrome?


Ubuntu 32 бит

+0

ли он работать, когда вы загрузили меньше \ *. Почтовый файл? Ошибка выглядит знакомой для меня, «вне памяти». – Hydro

+0

Да, это сработало, просто для больших реальных –

+0

Хм ... можете ли вы попытаться предупредить что-либо, когда срабатывает событие btn click? Когда ошибка будет сброшена, сообщите нам количество оповещений, которые вы получили здесь – Hydro

ответ

6

Загрузка 1gb + с AJAX не удобно только для мониторинга загрузки прогресса и заполнения памяти.

Вместо этого я просто отправлю файл с заголовком Content-Disposition, чтобы сохранить файл.


Есть, однако, способы обойти его, чтобы следить за прогрессом. Первый вариант состоит в том, чтобы иметь второй websocket, который сигнализирует, сколько вы загрузили, когда вы обычно загружаете запрос на получение. другой вариант будет описан ниже в нижнем


Я знаю, вы говорили об использовании Мгновения песочницы файловой системы в разговоре. но имеет некоторые недостатки. При использовании постоянного хранилища может потребоваться разрешение. Это позволяет оставить только 20% доступного диска. И если хром должен освободить некоторое пространство, тогда он выбросит любые другие временные хранилища доменов, которые в последний раз использовались для самого последнего файла. Кроме того, он не работает в приватном режиме.
Не говоря уже о том, что она понижалась его поддержку и никогда не может оказаться в других браузерах - но они, скорее всего, не удалить его, так как многие сайты по-прежнему зависит от него


Единственный способ обработки этого большой файл с потоками. Вот почему я создал StreamSaver. Это будет работать только в банкомате Blink (chrome &), но в конечном итоге он будет поддерживаться другими браузерами с спецификацией whatwg для резервного копирования в качестве стандарта.

fetch(url).then(res => { 
    // One idea is to get the filename from Content-Disposition header... 
    const size = ~~res.headers.get('Content-Length') 
    const fileStream = streamSaver.createWriteStream('filename.zip', size) 
    const writeStream = fileStream.getWriter() 
    // Later you will be able to just simply do 
    // res.body.pipeTo(fileStream) 
    // instead of pumping 

    const reader = res.body.getReader() 
    const pump =() => reader.read() 
     .then(({ value, done }) => { 
      // here you know how large the value (chunk) is and you can 
      // figure out the download speed/progress when comparing it to the size 

      return done 
       ? writeStream.close() 
       : writeStream.write(value).then(pump) 
     ) 

    // Start the reader 
    pump().then(() => 
     console.log('Closed the stream, Done writing') 
    ) 
}) 

Это не будет занимать любую память

+0

Могу ли я создать расширение, которое делает больше и меньше того же самого для firefox? Там есть работа? –

+0

Практически все возможно с расширением firefox, поэтому я так думаю. Но я не думаю, что люди установят его: -/вы могли бы внести свой вклад, помогая firefox реализовать потоки вместо этого :-) – Endless

4

У меня есть теория, что если вы разбить файл на куски и хранить их в IndexedDB а затем объединить их вместе, это будет работать

капля не из данных ... это больше похоже на указатели туда, где файл может быть прочитан из enter image description here

Значение, если вы храните их в индексированной, а затем сделать что-то вроде этого (с помощью FileSaver или альтернатива)

finalBlob = new Blob([blob_A_fromDB, blob_B_fromDB]) 
saveAs(finalBlob, 'filename.zip') 

Но я не могу подтвердить это, так как я не проверял, было бы хорошо, если кто-то может

+1

Я начал его тестировать. И я думаю, что это работает :) помогите мне просмотреть эту проблему: https://github.com/jimmywarting/StreamSaver.js/pull/18 – Endless

+0

Я тоже пытался, но у меня нет времени:/ Разработка слишком поздно –

+0

От файл с 450 МБ пошел хорошо –

 Смежные вопросы

  • Нет связанных вопросов^_^