Vla*_*anu 25 javascript html5 large-files websocket fileapi
我正在尝试使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我会上传使用:
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
基本上这会立即返回,bufferedAmount保持不变(0)并且它会继续迭代并在尝试发送之前将所有切片添加到队列中; 没有socket.afterSend允许我正确排队,这就是我被困住的地方.
Gra*_*ham 10
我相信这个send()方法是异步的,这就是为什么它会立即返回.要使其排队,您需要服务器在上传每个切片后将消息发送回客户端; 然后,客户端可以决定是否需要将下一个片段或"上传完成"消息发送回服务器.
使用XMLHttpRequest(2)可能会更容易这种事情; 它内置了回调支持,并且比WebSocket API支持得更广泛.
使用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.
Run Code Online (Sandbox Code Playgroud)
编辑:自从做出此答案以来,网络世界,浏览器,防火墙,代理发生了很大变化。目前,使用websocket发送文件可以高效完成,尤其是在局域网上。
Websocket对于双向通信非常有效,尤其是当您有兴趣从服务器推送信息(最好是小的信息)时。它们充当双向套接字(因此得名)。
在这种情况下,Websocket看起来不像是正确的技术。特别是考虑到使用它们会增加与某些代理,浏览器(IE)甚至防火墙的不兼容性。
另一方面,上传文件只是将POST请求发送到主体中包含文件的服务器。浏览器非常擅长于此,大文件的开销几乎没有。不要将websockets用于该任务。
为了序列化此操作,您需要服务器在每次接收和写入片段(或发生错误)时向您发送信号,这样您就可以发送下一个片段以响应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.
}
}
}
Run Code Online (Sandbox Code Playgroud)