Javascript 使用 WebSocket 上传大文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11080112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Large file upload with WebSocket
提问by Vlad Ciobanu
I'm trying to upload large files (at least 500MB, preferably up to a few GB) using the WebSocket API. The problem is that I can't figure out how to write "send this slice of the file, release the resources used then repeat". I was hoping I could avoid using something like Flash/Silverlight for this.
我正在尝试使用 WebSocket API 上传大文件(至少 500MB,最好是几 GB)。问题是我不知道如何编写“发送文件的这一部分,释放使用的资源然后重复”。我希望我可以避免为此使用 Flash/Silverlight 之类的东西。
Currently, I'm working with something along the lines of:
目前,我正在处理以下方面的事情:
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);
}
}
Then, I would upload using:
然后,我会上传使用:
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
}
}
}
Basically this returns immediately, bufferedAmount is unchanged (0) and it keeps iterating and adding all the slices to the queue before attempting to send it; there's no socket.afterSend to allow me to queue it properly, which is where I'm stuck.
基本上这会立即返回,bufferedAmount 不变(0)并且它在尝试发送之前不断迭代并将所有切片添加到队列中;没有 socket.afterSend 可以让我正确排队,这就是我卡住的地方。
采纳答案by Denys Séguret
EDIT : The web world, browsers, firewalls, proxies, changed a lot since this answer was made. Right now, sending files using websockets can be done efficiently, especially on local area networks.
编辑:自从做出这个答案以来,网络世界、浏览器、防火墙、代理发生了很大变化。现在,可以有效地使用 websockets 发送文件,尤其是在局域网上。
Websockets are very efficient for bidirectional communication, especially when you're interested in pushing information (preferably small) from the server. They act as bidirectional sockets (hence their name).
Websockets 对于双向通信非常有效,尤其是当您有兴趣从服务器推送信息(最好是小)时。它们充当双向套接字(因此得名)。
Websockets don't look like the right technology to use in this situation. Especially given that using them adds incompatibilities with some proxies, browsers (IE) or even firewalls.
Websockets 看起来不是在这种情况下使用的正确技术。特别是考虑到使用它们会增加与某些代理、浏览器 (IE) 甚至防火墙的不兼容。
On the other end, uploading a file is simply sending a POST request to a server with the file in the body. Browsers are very good at that and the overhead for a big file is really near nothing. Don't use websockets for that task.
另一方面,上传文件只是将 POST 请求发送到正文中包含该文件的服务器。浏览器在这方面非常擅长,大文件的开销几乎为零。不要将 websockets 用于该任务。
回答by Graham
I believe the send()
method is asynchronous which is why it will return immediately. To make it queue, you'd need the server to send a message back to the client after each slice is uploaded; the client can then decide whether it needs to send the next slice or a "upload complete" message back to the server.
我相信该send()
方法是异步的,这就是它会立即返回的原因。要使其排队,您需要服务器在每个切片上传后将消息发送回客户端;然后客户端可以决定是否需要将下一个切片或“上传完成”消息发送回服务器。
This sort of thing would probably be easier using XMLHttpRequest(2); it has callback support built-in and is also more widely supported than the WebSocket API.
使用 XMLHttpRequest(2) 可能会更容易;它具有内置的回调支持,并且比 WebSocket API 得到更广泛的支持。
回答by Konga Raju
Use web workers for large files processing instead doing it in main thread and upload chunks of file data using file.slice()
.
使用 Web Worker 处理大文件,而不是在主线程中执行,并使用file.slice()
.
This articlehelps you to handle large files in workers. change XHR send to Websocket in main thread.
此文章帮您解决工人的大型文件。在主线程中更改 XHR 发送到 Websocket。
//Messages from worker
function onmessage(blobOrFile) {
ws.send(blobOrFile);
}
//construct file on server side based on blob or chunk information.
回答by Demetrius Amadeus
In order to serialize this operation you need the server to send you a signal every time a slice is received & written (or an error occurs), this way you could send the next slice in response to the onmessageevent, pretty much like this:
为了序列化此操作,您需要服务器在每次接收和写入切片(或发生错误)时向您发送信号,这样您就可以发送下一个切片以响应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.
}
}
}
回答by Ibrahim Muhammad
You could use https://github.com/binaryjs/binaryjsor https://github.com/liamks/Delivery.jsif you can run node.js on the server.
如果您可以在服务器上运行 node.js,您可以使用https://github.com/binaryjs/binaryjs或https://github.com/liamks/Delivery.js。
回答by Kesarion
I think this socket.io project has a lot of potential:
我认为这个 socket.io 项目有很大的潜力:
https://github.com/sffc/socketio-file-upload
https://github.com/sffc/socketio-file-upload
It supports chunked upload, progress tracking and seems fairly easy to use.
它支持分块上传、进度跟踪,而且看起来相当容易使用。