Большая загрузка файлов с помощью WebSocket - программирование
Подтвердить что ты не робот

Большая загрузка файлов с помощью WebSocket

Я пытаюсь загрузить большие файлы (не менее 500 МБ, желательно до нескольких ГБ), используя API WebSocket. Проблема в том, что я не могу понять, как написать "отправить этот фрагмент файла, освободить используемые ресурсы, а затем повторить". Я надеялся, что смогу избежать использования чего-то типа Flash/Silverlight для этого.

В настоящее время я работаю с чем-то вроде:

function FileSlicer(file) {
    // randomly picked 1MB slices,
    // I don't think this size is important for this experiment
    this.sliceSize = 1024*1024;  
    this.slices = Math.ceil(file.size / this.sliceSize);

    this.currentSlice = 0;

    this.getNextSlice = function() {
        var start = this.currentSlice * this.sliceSize;
        var end = Math.min((this.currentSlice+1) * this.sliceSize, file.size);
        ++this.currentSlice;

        return file.slice(start, end);
    }
}

Затем я загружу, используя:

function Uploader(url, file) {
    var fs = new FileSlicer(file);
    var socket = new WebSocket(url);

    socket.onopen = function() {
        for(var i = 0; i < fs.slices; ++i) {
            socket.send(fs.getNextSlice()); // see below
        }
    }
}

В основном это немедленно возвращается, bufferedAmount не изменяется (0), и он продолжает итерацию и добавляет все срезы в очередь, прежде чем пытаться ее отправить; там нет socket.afterSend, чтобы позволить мне правильно стоять в очереди, где я застрял.

4b9b3361

Ответ 1

EDIT: веб-мир, браузеры, брандмауэры, прокси, сильно изменились с тех пор, как был получен этот ответ. Прямо сейчас, отправка файлов с помощью websockets могут быть выполнены эффективно, особенно в локальных сетях.

Websockets очень эффективны для двунаправленной связи, особенно если вы заинтересованы в том, чтобы выталкивать информацию (желательно небольшую) с сервера. Они действуют как двунаправленные сокеты (отсюда и их название).

Веб-узлы не похожи на правильную технологию для использования в этой ситуации. Особенно учитывая, что использование их добавляет несовместимости с некоторыми прокси, браузерами (IE) или даже брандмауэрами.

С другой стороны, загрузка файла просто отправляет запрос POST на сервер с файлом в теле. Браузеры очень хороши в этом, и накладные расходы для большого файла практически ничего не стоят. Не используйте веб-узлы для этой задачи.

Ответ 2

Я считаю, что метод send() является асинхронным, поэтому он немедленно возвращается. Чтобы сделать это в очереди, вам нужно, чтобы сервер отправил сообщение клиенту после загрузки каждого фрагмента; клиент может затем решить, нужно ли отправить следующий фрагмент или сообщение "загрузить полный" на сервер.

Подобным образом, возможно, будет проще использовать XMLHttpRequest (2); он имеет встроенную поддержку обратного вызова и также более широко поддерживается, чем API WebSocket.

Ответ 3

Используйте веб-работников для обработки больших файлов, вместо этого делайте это в основном потоке и загружайте куски файлов с помощью file.slice().

Эта статья помогает обрабатывать большие файлы у рабочих. измените XHR на веб-узел в основной теме.

//Messages from worker
function onmessage(blobOrFile) {
 ws.send(blobOrFile);
}

//construct file on server side based on blob or chunk information.

Ответ 4

Чтобы сериализовать эту операцию, сервер должен посылать вам сигнал каждый раз, когда срез принимается и записывается (или возникает ошибка), таким образом вы можете отправить следующий фрагмент в ответ на onmessage, примерно так:

function Uploader(url, file) {
    var fs = new FileSlicer(file);
    var socket = new WebSocket(url);

    socket.onopen = function() {
       socket.send(fs.getNextSlice());
    }
    socket.onmessage = function(ms){
        if(ms.data=="ok"){
           fs.slices--;
           if(fs.slices>0) socket.send(fs.getNextSlice());
        }else{
           // handle the error code here.
        }
    }
}

Ответ 6

Я думаю, что у этого проекта socket.io большой потенциал:

https://github.com/sffc/socketio-file-upload

Он поддерживает загрузку по частям, отслеживание прогресса и кажется довольно простым в использовании.