javascript - w3cwebsocket - websocket node js express
Carga de archivos grandes con WebSocket (5)
Creo que el método send()
es asíncrono, por lo que volverá inmediatamente. Para hacer la cola, necesitaría que el servidor envíe un mensaje al cliente después de que se haya cargado cada porción; el cliente puede decidir si necesita enviar la siguiente porción o un mensaje de "carga completa" al servidor.
Este tipo de cosas probablemente sería más fácil usando XMLHttpRequest (2); tiene soporte de devolución de llamada integrado y también es más compatible que la API de WebSocket.
Estoy tratando de cargar archivos grandes (al menos 500 MB, preferiblemente hasta unos pocos GB) usando la API de WebSocket. El problema es que no puedo averiguar cómo escribir "enviar esta porción del archivo, liberar los recursos utilizados y luego repetir". Esperaba poder evitar usar algo como Flash / Silverlight para esto.
Actualmente, estoy trabajando en algo como:
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);
}
}
Entonces, subiría usando:
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
}
}
}
Básicamente esto se devuelve de inmediato, bufferedAmount no se modifica (0) y se mantiene iterando y agregando todos los segmentos a la cola antes de intentar enviarlo; no hay socket.afterSend para permitirme hacer una cola correctamente, que es donde estoy atascado.
Para serializar esta operación, necesita que el servidor le envíe una señal cada vez que se reciba y se escriba una porción (o se produzca un error), de esta manera podría enviar la siguiente porción en respuesta al evento onmessage , más o menos así:
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.
}
}
}
Puede usar https://github.com/binaryjs/binaryjs o https://github.com/liamks/Delivery.js si puede ejecutar node.js en el servidor.
Utilice trabajadores web para el procesamiento de archivos grandes en lugar de hacerlo en el hilo principal y cargue trozos de datos de archivos usando file.slice()
.
Este article te ayuda a manejar archivos grandes en trabajadores. cambiar XHR enviar a Websocket en el hilo principal.
//Messages from worker
function onmessage(blobOrFile) {
ws.send(blobOrFile);
}
//construct file on server side based on blob or chunk information.
EDITAR: El mundo web, los navegadores, los cortafuegos, los proxies, cambiaron mucho desde que se hizo esta respuesta. En este momento, el envío de archivos mediante websockets se puede realizar de manera eficiente, especialmente en redes de área local.
Los websockets son muy eficientes para la comunicación bidireccional, especialmente cuando está interesado en enviar información (preferiblemente pequeña) desde el servidor. Actúan como zócalos bidireccionales (de ahí su nombre).
Los websockets no parecen la tecnología adecuada para usar en esta situación. Especialmente dado que usarlos agrega incompatibilidades con algunos proxies, navegadores (IE) o incluso firewalls.
En el otro extremo, cargar un archivo es simplemente enviar una solicitud POST a un servidor con el archivo en el cuerpo. Los navegadores son muy buenos en eso y la sobrecarga de un archivo grande no es nada. No utilice websockets para esa tarea.