Domanda Caricamento di file di grandi dimensioni con WebSocket


Sto cercando di caricare file di grandi dimensioni (almeno 500 MB, preferibilmente fino a pochi GB) utilizzando l'API WebSocket. Il problema è che non riesco a capire come scrivere "invia questa porzione del file, rilascia le risorse utilizzate e poi ripeti". Speravo di poter evitare di usare qualcosa come Flash / Silverlight per questo.

Attualmente sto lavorando a qualcosa sulla falsariga di:

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);
    }
}

Quindi, vorrei caricare utilizzando:

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
        }
    }
}

Fondamentalmente questo ritorna immediatamente, bufferedAmount è invariato (0) e continua a ripetere e aggiungere tutte le slice alla coda prima di tentare di inviarlo; non c'è socket.afterSend per consentirmi di accodarlo correttamente, che è dove sono bloccato.


18
2018-06-18 09:27


origine


risposte:


EDIT: Il mondo web, i browser, i firewall, i proxy, sono cambiati molto da quando è stata fatta questa risposta. In questo momento, l'invio di file tramite websockets può essere fatto in modo efficiente, specialmente sulle reti locali.

I Websocket sono molto efficienti per la comunicazione bidirezionale, specialmente quando sei interessato a spingere le informazioni (preferibilmente di piccole dimensioni) dal server. Funzionano come prese bidirezionali (da qui il loro nome).

Le web socket non sembrano la tecnologia giusta da usare in questa situazione. Soprattutto dato che il loro utilizzo aggiunge incompatibilità con alcuni proxy, browser (IE) o persino firewall.

D'altra parte, il caricamento di un file è semplicemente l'invio di una richiesta POST a un server con il file nel corpo. I browser sono molto bravi in ​​questo e il sovraccarico per un file di grandi dimensioni è davvero vicino a nulla. Non utilizzare websocket per tale attività.


5
2018-06-18 10:56



Io credo send() il metodo è asincrono ed è per questo che ritornerà immediatamente. Per farlo in coda, è necessario che il server invii un messaggio al client dopo che ogni fetta è stata caricata; il cliente può quindi decidere se è necessario inviare il prossimo slice o un messaggio "upload complete" al server.

Questo tipo di cose sarebbe probabilmente più semplice usando XMLHttpRequest (2); ha il supporto per callback integrato ed è anche più ampiamente supportato rispetto all'API WebSocket.


10
2018-06-18 09:47



Utilizza i web worker per l'elaborazione di file di grandi dimensioni invece di eseguirli nel thread principale e caricare blocchi di dati di file usando file.slice().

Questo articolo ti aiuta a gestire file di grandi dimensioni in lavoratori. cambia XHR invia a Websocket nella discussione principale.

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

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

7
2018-06-27 06:08



Per serializzare questa operazione è necessario che il server invii un segnale ogni volta che una slice viene ricevuta e scritta (o si verifica un errore), in questo modo è possibile inviare la slice successiva in risposta al onMessage evento, più o meno così:

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.
        }
    }
}

4
2017-08-25 19:53



Potresti usare https://github.com/binaryjs/binaryjs o https://github.com/liamks/Delivery.js se è possibile eseguire node.js sul server.


3
2017-07-03 17:47