为了使用域名碎片来实现并行上传,我不得不给Node.js应用做些修改。我第一个要修改的是让Node.js应用支持跨域资源共享。我不得不这样做是因为使用域碎片实际上是让一个请求分到不同的域并且同源策略会限制我的这个请求。
好消息是XMLttPRequest 标准2规范允许我这么做,如果网站已经把跨域资源共享打开,更好的是我不用为了实现这个而变更在"workeruploadchunk.js"里的上传方法。
// 使用跨域资源共享 // Taken from
var enableCORS = function(request,response, next){
response.header('Access-Control-Allow-Origin', '*');
response.header('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
response.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-
Length, X-Requested-With' ) ;
// 拦截OPTIONS方法
if ('OPTIONS' ==request.method){
response.send(204);
}
else {
next();
}
} ;
// 在表达式中使用跨域资源共享
app. use ( enableCORS ) ;
为了使server.js文件中得CORS可用,我创建了一个函数,该函数会创建必要的头以表明Node.js应用支持CORS。另一件事是我还需要表明CORS支持两种请求,他们是:
简单请求:
1、只用GET,HEAD或POST。如果使用POST向服务器发送数据,那么发送给服务器的HTTP POST请求的Content-Type应是application/x-www-form-urlencoded, multipart/form-data, 或 text/plain其中的一个。
2、HTTP请求中不要设置自定义的头(例如X-Modified等)
预检请求:
1、使用GET,HEAD或POST以外的方法。假设使用POST发送请求,那么Content-Type不能是application/x-www-form-urlencoded, multipart/form-data, or text/plain,例如假设POST请求向服务器发送了XML有效载荷使用了application/xml or text/xml,那么这个请求就是预检的。
2、在请求中设置自定义头(比如请求使用X-PINGOTHER头)。
在我们的例子中,我们用的是简单请求,所以我们不需要做其他得工作以使例子能够工作。
在 "workeruploadchunk.js" 文件中,我向 self.onmessage 事件添加了对进行并行文件数据块上传的支持.
// We are going to upload to a backend that supports parallel uploads.
// Parallel uploads is supported by publishng the web site on different ports
// The backen must implement CORS for this to work
else if(workerdata.chunk!= null&& workerdata.paralleluploads ==true){
if (urlnumber >= 6) {
urlnumber = 0;
}
if (urlcount >= 6) {
urlcount = 0;
}
if (urlcount == 0) {
uploadurl = workerdata.currentlocation +webapiUrl + urlnumber;
}
else {
// Increment the port numbers, e.g 8000, 8001, 8002, 8003, 8004, 8005
uploadurl = workerdata.currentlocation.slice(0, -1) + urlcount +webapiUrl +
urlnumber;
}
upload(workerdata.chunk,workerdata.filename,workerdata.chunkCount, uploadurl,
workerdata.asyncstate);
urlcount++;
urlnumber++;
}
在 Default.html 页面我对当前的URL进行了保存,因为我准备把这些信息发送给文件上传的工作程序. 只所以这样做是因为:
我想要利用这个信息增加端口数量
做了 CORS 请求,我需要把完整的 URL 发送给 XMLHttpRequest 对象.
<div>
<spanLucida Console"; font-size: 8.0pt;">// Save current protocol and host for parallel uploads</span></div>
<div>
"font-family: 'Lucida Console'; font-size: 8pt;"><span>var</span><span> currentProtocol </span><span>= </span><span>window.</span><span>location</span><span>.</span><span>protocol</span><span>;</span></div>
<div>
"font-family: 'Lucida Console'; font-size: 8pt;"><span>var</span><span> currentHostandPort </span><span>=</span><span> window.</span><span>location</span><span>.</span><span>host</span><span>;</span></div>
<div>
"font-family: 'Lucida Console'; font-size: 8pt;"><span>var</span><span> currentLocation </span><span>= </span><span>currentProtocol </span><span>+</span><span> </span><span>"//"</span><span> </span><span>+</span><span> currentHostandPort</span><span>;</span></div>
<spanCalibri","sans-serif"; font-size: 11.0pt; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">
</span>
<spanCalibri","sans-serif"; font-size: 11.0pt; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">The code below shows the modification made to the upload message.</span><span><o:p></o:p></span>
<spanCalibri","sans-serif"; font-size: 11.0pt; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">
</span>
<span>// Send and upload message to the webworker</span>
"background-color: #ffff99; font-family: 'Lucida Console'; font-size: 8pt;"><span>case</span><span> </span><span>'upload'</span><span>:</span>
<span>// </span><span>Check to see if backend supports parallel uploads</span>
var paralleluploads =false;
if ($('#select_parallelupload').prop('checked')) {
paralleluploads = true;
}
uploadworkers[data.id].postMessage({ 'chunk': data.blob, 'filename':data.filename,
'directory': $("#select_directory").val(), 'chunkCount':data.chunkCount,
'asyncstate':data.asyncstate,'paralleluploads':paralleluploads, 'currentlocation':
currentLocation, 'id': data.id });
break;
最后修改了 CelerFT 接口来支持并行上传.
带有并行上传的CelerFT
这个项目的代码可以再我的 github 资源库上找到