34

我正在尝试使用 WebSocket API 上传大文件(至少 500MB,最好达到几 GB)。问题是我不知道如何编写“发送这部分文件,释放使用的资源然后重复”。我希望我可以避免为此使用 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 可以让我正确排队,这就是我卡住的地方。

4

6 回答 6

10

我相信该send()方法是异步的,这就是它会立即返回的原因。要使其排队,您需要服务器在每个切片上传后向客户端发送一条消息;然后客户端可以决定是否需要将下一个切片或“上传完成”消息发送回服务器。

这种事情使用 XMLHttpRequest(2) 可能会更容易;它内置了回调支持,并且比 WebSocket API 得到更广泛的支持。

于 2012-06-18T09:47:15.263 回答
10

使用 web worker 处理大文件,而不是在主线程中处理,并使用file.slice().

本文帮助您处理工作人员的大文件。在主线程中更改 XHR 发送到 Websocket。

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

//construct file on server side based on blob or chunk information.
于 2014-06-27T06:08:17.760 回答
5

为了序列化此操作,您需要服务器在每次接收和写入切片(或发生错误)时向您发送信号,这样您可以发送下一个切片以响应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.
        }
    }
}
于 2013-08-25T19:53:13.913 回答
4

编辑:自从做出这个答案以来,网络世界、浏览器、防火墙、代理发生了很大变化。现在,使用 websockets 发送文件可以很高效地完成,尤其是在局域网上。

Websockets 对于双向通信非常有效,尤其是当您有兴趣从服务器推送信息(最好是小的)时。它们充当双向套接字(因此得名)。

Websockets 看起来不像是在这种情况下使用的正确技术。特别是考虑到使用它们会增加与某些代理、浏览器 (IE) 甚至防火墙的不兼容性。

另一方面,上传文件只是简单地向服务器发送一个 POST 请求,文件在正文中。浏览器在这方面非常擅长,大文件的开销几乎没有。不要将 websockets 用于该任务。

于 2012-06-18T10:56:55.823 回答
3

如果可以在服务器上运行 node.js,则可以使用https://github.com/binaryjs/binaryjshttps://github.com/liamks/Delivery.js 。

于 2013-07-03T17:47:22.440 回答
0

我认为这个socket.io项目有很大的潜力:

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

它支持分块上传、进度跟踪,并且看起来相当容易使用。

于 2019-08-17T16:23:15.007 回答