主页»NodeJS»运用 HTTP 上传 G 级的文件之 Node.js 版别

运用 HTTP 上传 G 级的文件之 Node.js 版别

来历:oschina 发布时刻:2014-11-05 阅览次数:

  不论喜爱与否,javascript无处不在。 咱们能够在客户端的前台运用中找到它,也能够在很多的结构、类库中找到它,而且能够在服务器端的后台运用中找到它。

  近年来, Javascript越来越盛行,这似乎是由于 Javascript 生态体系正在协助进步生产率、削减入门所需的时刻。 在我的 榜首篇文章中,我介绍了运用 ASP.NET Web 后端 API 完结 G级文件上传,宣布完这篇文章后,我决议试一下运用 Node.js 能否到达相同的作用。  这意味着我需求完结 UploadChunk和 MergeAll办法,在 Node.js中我宣布的 最终一篇文章谈到了这一点。

 开发环境

  咱们将运用 Visual Studio Express 2013 for Web 作为开发环境, 不过它还不能被用来做 Node.js 开发。为此咱们需求装置 Node.js Tools for Visual Studio。  装好后 Visual Studio Express 2013 for Web 就会转变成一个 Node.js IDE 环境,供给创立这个运用所需求的全部东西.。而根据这儿供给的辅导,咱们需求:

  装置完结后咱们就会运转 Visual Studio Express 2013 for Web, 并运用 Node.js 的交互窗口来验证装置. Node.js 的交互窗口能够再 View->Other Windows->Node.js Interactive Window 下找到. Node.js 交互窗口运转后咱们要输入一些指令查看是否全部OK.

Figure 1 Node.js Interactive Window

  现在咱们现已对装置进行了验证,咱们现在就能够预备开端创立支撑GB级文件上传的Node.js后台程序了. 开端咱们先创立一个新的项目,并挑选一个空的 Node.js Web运用程序模板.

Figure 2 New project using the Blank Node.js Web Application template

  项目创立好今后,咱们应该会看到一个叫做 server.js 的文件,还有解决方案阅览器里边的Node包管理器 (npm). 

图3 解决方案管理器里边的 Node.js 运用程序

  server.js 文件里边有需求运用Node.js来创立一个根底的hello world运用程序的代码.

Figure 4 The Hello World application

  我现在持续把这段代码从 server.js 中删去,然后在Node.js中穿件G等级文件上传的后端代码。下面我需求用npm装置这个项目需求的一些依靠:

  •  Express - Node.js网页运用结构,用于构建单页面、多页面以及混合网络运用

  •  Formidable - 用于解析表单数据,特别是文件上传的Node.js模块

  •  fs-extra - 文件体系交互模块 

图5 运用npm装置所需模块

  模块装置完结后,咱们能够从解决方案资源管理器中看到它们。


 

图6 解决方案资源管理器显现已装置模块

  下一步咱们需求在解决方案资源管理器新建一个 "Scripts" 文件夹而且添加  "workeruploadchunk.js" 和   "workerprocessfile.js" 到该文件夹。咱们还需求下载 jQuery 2.x 和  SparkMD5 库并添加到"Scripts"文件夹。 最终还需求添加 "Default.html" 页面。这些都在我之前的 post 中介绍过。

 创立Node.js后台

  首要咱们需求用Node.js的"require()"函数来导入在后台上传G级文件的模块。留意我也导入了"path"以及"crypto" 模块。"path"模块供给了生成上传文件块的文件名的办法。"crypto" 模块供给了生成上传文件的MD5校验和的办法。

// The required modules        
var   express = require('express');      
var   formidable = require('formidable');      
var   fs = require('fs-extra');      
var   path = require('path');  
var   crypto = require('crypto');

  下一行代码便是见证奇观的时刻。

<span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-removed: initial; background-repeat: initial; background-size: initial; color: #000066; font-family: Consolas; font-size: 9pt;">var</span><span style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-removed: initial; background-repeat: initial; background-size: initial; font-family: Consolas; font-size: 9pt;"> app <span style="color: #339933;">=</span> express<span style="color: #009900;">()</span><span style="color: #339933;">;</span></span>

  这行代码是用来创立express运用的。express运用是一个封装了Node.js底层功用的中间件。假如你还记得那个由Blank Node.js Web运用模板创立的"Hello World" 程序,你会发现我导入了"http"模块,然后调用了"http.CreateServer()"办法创立了 "Hello World" web运用。咱们刚刚创立的express运用内建了全部的功用。

  现在咱们现已创立了一个express运用,咱们让它出现之前创立的"Default.html",然后让运用等候衔接。

// Serve up the Default.html page  
app.use(express.static(__dirname, { index: 'Default.html' }));      
 
// Startup the express.js application  
app.listen(process.env.PORT || 1337);      
 
// Path to save the files  
var   uploadpath = 'C:/Uploads/CelerFT/';

  express运用有app.VERB()办法,它供给了路由的功用。咱们将运用app.post()办法来处理"UploadChunk" 恳求。在app.post()办法里咱们做的榜首件事是查看咱们是否在处理POST恳求。接下去查看Content-Type是否是mutipart/form-data,然后查看上传的文件块巨细不能大于51MB。

// Use the post method for express.js to respond to posts to the uploadchunk urls and  
// save each file chunk as a separate file  
app.post('*/api/CelerFTFileUpload/UploadChunk*', function(request,response) {      
 
    if (request.method === 'POST') {      
        // Check Content-Type     
        if (!(request.is('multipart/form-data'))){      
            response.status(415).send('Unsupported media type');      
            return;      
        }      
  
        // Check that we have not exceeded the maximum chunk upload size  
        var maxuploadsize =51 * 1024 * 1024;      
 
        if (request.headers['content-length']> maxuploadsize){      
            response.status(413).send('Maximum upload chunk size exceeded');      
            return;      
        }

  一旦咱们成功经过了全部的查看,咱们将把上传的文件块作为一个独自分隔的文件并将它按次序数字命名。下面最重要的代码是调用fs.ensureDirSync()办法,它运用来查看暂时目录是否存在。假如目录不存在则创立一个。留意咱们运用的是该办法的同步版别。

// Get the extension from the file name  
var extension =path.extname(request.param('filename'));      
 
// Get the base file name  
var baseFilename =path.basename(request.param('filename'), extension);      
 
// Create the temporary file name for the chunk  
var tempfilename =baseFilename + '.'+      
request.param('chunkNumber').toString().padLeft('0', 16) + extension + ".tmp";      
 
 
// Create the temporary directory to store the file chunk  
// The temporary directory will be based on the file name  
var tempdir =uploadpath + request.param('directoryname')+ '/' + baseFilename;      
 
// The path to save the file chunk  
var localfilepath =tempdir + '/'+ tempfilename;      
 
if (fs.ensureDirSync(tempdir)) {      
    console.log('Created directory ' +tempdir);  
}

  正如我之前提出的,咱们能够经过两种办法上传文件到后端服务器。榜首种办法是在web阅览器中运用FormData,然后把文件块作为二进制数据发送,另一种办法是把文件块转换成base64编码的字符串,然后创立一个手艺的multipart/form-data encoded恳求,然后发送到后端服务器。  

  所以咱们需求查看一下是否在上传的是一个手艺multipart/form-data encoded恳求,经过查看"CelerFT-Encoded"头部信息,假如这个头部存在,咱们创立一个buffer并运用request的ondata时刻把数据复制到buffer中。

  在request的onend作业中经过将buffer出现为字符串并按CRLF分隔,然后从 multipart/form-data encoded恳求中提取base64字符串。base64编码的文件块能够在数组的第四个索引中找到。

  经过创立一个新的buffer来将base64编码的数据重现转换为二进制。随后调用fs.outputFileSync()办法将buffer写入文件中。

// Check if we have uploaded a hand crafted multipart/form-data request  
// If we have done so then the data is sent as a base64 string  
// and we need to extract the base64 string and save it  
if (request.headers['celerft-encoded']=== 'base64') {     
 
    var fileSlice = newBuffer(+request.headers['content-length']);      
    var bufferOffset = 0;      
 
    // Get the data from the request  
    request.on('data', function (chunk) {      
        chunk.copy(fileSlice , bufferOffset);      
        bufferOffset += chunk.length;      
    }).on('end', function() {      
        // Convert the data from base64 string to binary  
        // base64 data in 4th index of the array  
        var base64data = fileSlice.toString().split('\r\n');      
        var fileData = newBuffer(base64data[4].toString(), 'base64');      
 
        fs.outputFileSync(localfilepath,fileData);      
        console.log('Saved file to ' +localfilepath);      
 
        // Send back a sucessful response with the file name  
        response.status(200).send(localfilepath);      
        response.end();      
    });  
}

  二进制文件块的上传是经过formidable模块来处理的。咱们运用formidable.IncomingForm()办法得到multipart/form-data encoded恳求。formidable模块将把上传的文件块保存为一个独自的文件并保存到暂时目录。咱们需求做的是在formidable的onend作业中将上传的文件块保存为里一个姓名。

else {      
    // The data is uploaded as binary data.      
    // We will use formidable to extract the data and save it      
    var form = new formidable.IncomingForm();      
    form.keepExtensions = true;      
    form.uploadDir = tempdir;     
 
    // Parse the form and save the file chunks to the      
    // default location      
    form.parse(request, function (err, fields, files) {      
        if (err){      
            response.status(500).send(err);      
            return;      
        }      
 
    //console.log({ fields: fields, files: files });      
    });      
 
    // Use the filebegin event to save the file with the naming convention      
    /*form.on('fileBegin', function (name, file) {  
    file.path = localfilepath;  
});*/        
 
form.on('error', function (err) {      
        if (err){      
            response.status(500).send(err);      
            return;      
        }      
    });      
 
    // After the files have been saved to the temporary name      
    // move them to the to teh correct file name      
    form.on('end', function (fields,files) {      
        // Temporary location of our uploaded file             
        var temp_path = this.openedFiles[0].path;      
 
        fs.move(temp_path , localfilepath,function (err){      
 
            if (err) {      
                response.status(500).send(err);      
                return;      
            }      
            else {      
                // Send back a sucessful response with the file name      
                response.status(200).send(localfilepath);      
                response.end();      
            }     
        });     
    });      
 
// Send back a sucessful response with the file name      
//response.status(200).send(localfilepath);      
//response.end();      
}  
}

  app.get()办法运用来处理"MergeAll"恳求的。这个办法完结了之前描绘过的功用。

// Request to merge all of the file chunks into one file  
app.get('*/api/CelerFTFileUpload/MergeAll*', function(request,response) {      
 
    if (request.method === 'GET') {      
 
        // Get the extension from the file name  
        var extension =path.extname(request.param('filename'));      
 
        // Get the base file name  
        var baseFilename =path.basename(request.param('filename'), extension);      
 
        var localFilePath =uploadpath + request.param('directoryname')+ '/' + baseFilename;      
 
        // Check if all of the file chunks have be uploaded  
        // Note we only wnat the files with a *.tmp extension  
        var files =getfilesWithExtensionName(localFilePath, 'tmp')      
        /*if (err) {  
            response.status(500).send(err);  
            return;  
        }*/  
 
        if (files.length !=request.param('numberOfChunks')){     
            response.status(400).send('Number of file chunks less than total count');      
            return;      
        }      
 
        var filename =localFilePath + '/'+ baseFilename +extension;      
        var outputFile =fs.createWriteStream(filename);      
 
        // Done writing the file  
        // Move it to top level directory  
        // and create MD5 hash  
        outputFile.on('finish', function (){      
            console.log('file has been written');      
            // New name for the file  
            var newfilename = uploadpath +request.param('directoryname')+ '/' + baseFilename  
            + extension;      
 
            // Check if file exists at top level if it does delete it  
            //if (fs.ensureFileSync(newfilename)) {  
            fs.removeSync(newfilename);      
            //} 
 
            // Move the file  
            fs.move(filename, newfilename ,function (err) {      
                if (err) {      
                    response.status(500).send(err);      
                    return;      
                }      
                else {      
                    // Delete the temporary directory  
                    fs.removeSync(localFilePath);      
                    varhash = crypto.createHash('md5'),      
                        hashstream = fs.createReadStream(newfilename);     
 
                    hashstream.on('data', function (data) {      
                        hash.update(data)      
                    });      
 
                    hashstream.on('end', function (){     
                        var md5results =hash.digest('hex');      
                        // Send back a sucessful response with the file name  
                        response.status(200).send('Sucessfully merged file ' + filename + ", "      
                        + md5results.toUpperCase());      
                        response.end();      
                    });      
                }      
            });      
        });      
 
        // Loop through the file chunks and write them to the file  
        // files[index] retunrs the name of the file.  
        // we need to add put in the full path to the file  
        for (var index infiles) {     
            console.log(files[index]);      
            var data = fs.readFileSync(localFilePath +'/' +files[index]);      
            outputFile.write(data);      
            fs.removeSync(localFilePath + '/' + files[index]);      
        }      
        outputFile.end();      
    }  
 
})   ;

  留意Node.js并没有供给String.padLeft()办法,这是经过扩展String完结的。

// String padding left code taken from  
// http://www.lm-tech.it/Blog/post/2012/12/01/String-Padding-in-Javascript.aspx  
String.prototype.padLeft = function (paddingChar, length) {      
    var s = new String(this);      
    if ((this.length< length)&& (paddingChar.toString().length > 0)) {      
        for (var i = 0; i < (length - this.length) ; i++) {      
            s = paddingChar.toString().charAt(0).concat(s);      
        }      
    }     
    return s;  
}   ;

 一些其它作业

  其间一件事是,宣布上篇文章后我持续研讨是为了经过域名碎片完结并行上传到CeleFT功用。域名碎片的原理是拜访一个web站点时,让web阅览器树立更多的超越正常答应规模的并发衔接。 域名碎片能够经过运用不同的域名(如web1.example.com,web2.example.com)或许不同的端口号(如8000, 8001)保管web站点的办法完结。

  示例中,咱们运用不同端口号保管web站点的办法。

  咱们运用 iisnode 把 Node.js集成到 IIS( Microsoft Internet Information Services)完结这一点。 下载兼容你操作体系的版别 iisnode (x86) 或许  iisnode (x64)。 下载 IIS URL重写包

  一旦装置完结(假定windows版Node.js已装置),到IIS管理器中创立6个新网站。将榜首个网站命名为CelerFTJS而且将侦听端口装备为8000。

图片7在IIS管理器中创立一个新网站

  然后创立其他的网站。我为每一个网站都创立了一个运用池,而且给运用池“LocalSystem”等级的权限。全部网站的本地途径是C:\inetpub\wwwroot\CelerFTNodeJS。

图片8 文件夹层级

  我在Release形式下编译了Node.js运用,然后我复制了server.js文件、Script文件夹以及node_modules文件夹到那个目录下。

  要让包括 iisnode 的Node.js的运用作业,咱们需求创立一个web.config文件,并在其间添加如下得内容。

<defaultDocument>  
    <files>  
      <add value="server.js" />  
    </files>  
  </defaultDocument>  
 
  <handlers>  
    <!-- indicates that the server.js file is a node.js application to be handled by the       
    iisnode module -->      
    <add name="iisnode" path="*.js" verb="*" modules="iisnode" />  
  </handlers>  
 
  <rewrite>  
    <rules>  
      <rule name="CelerFTJS">  
        <match url="/*" />  
        <action type="Rewrite" url="server.js" />  
      </rule>  
 
      <!-- Don't interfere with requests for node-inspector debugging -->      
      <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">  
        <match url="^server.js\/debug[\/]?" />  
      </rule>  
    </rules>  
  </rewrite>

  web.config中各项的意思是让iisnode处理全部得*.js文件,由server.js 处理任何匹配"/*"的URL。

图片9 URL重写规矩

  假如你正确的做完了全部的作业,你就能够经过http://localhost:8000阅览网站,并进入CelerFT "Default.html"页面。

  web.config文件被修正以支撑如前面post中所解说的大文件的上传,这儿我不会解说全部的项。不过下面的web.config项能够改进 iisnode中Node.js的功能。

<span style="font-family: Consolas; font-size: 9pt;"><iisnode</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;"> </span><span style="color: #000066; font-family: Consolas; font-size: 9.0pt;">node_env</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;">=</span><span style="color: red; font-family: Consolas; font-size: 9.0pt;">"production"</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;"> </span><span style="color: #000066; font-family: Consolas; font-size: 9.0pt;">debuggingEnabled</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;">=</span><span style="color: red; font-family: Consolas; font-size: 9.0pt;">"false"</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;"> </span><span style="color: #000066; font-family: Consolas; font-size: 9.0pt;">devErrorsEnabled</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;">=</span><span style="color: red; font-family: Consolas; font-size: 9.0pt;">"false"</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;"> </span><span style="color: #000066; font-family: Consolas; font-size: 9.0pt;">nodeProcessCountPerApplication</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;">=</span><span style="color: red; font-family: Consolas; font-size: 9.0pt;">"0"</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;"> </span><span style="color: #000066; font-family: Consolas; font-size: 9.0pt;">maxRequestBufferSize</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;">=</span><span style="color: red; font-family: Consolas; font-size: 9.0pt;">"52428800"</span><span style="color: #009900; font-family: Consolas; font-size: 9.0pt;"> </span><span style="font-family: Consolas; font-size: 9pt;">/></span><span style="font-family: Consolas; font-size: 9.0pt;"><o:p></o:p></span>

 并行上传 

  为了运用域名碎片来完结并行上传,我不得不给Node.js运用做些修正。我榜首个要修正的是让Node.js运用支撑跨域资源共享。我不得不这样做是由于运用域碎片实际上是让一个恳求分到不同的域而且同源战略会约束我的这个恳求。

  好音讯是XMLttPRequest 标准2标准答应我这么做,假如网站现已把跨域资源共享翻开,更好的是我不必为了完结这个而变更在"workeruploadchunk.js"里的上传办法。

// 运用跨域资源共享 // Taken from http://bannockburn.io/2013/09/cross-origin-resource-sharing-cors-with-a-node-js-express-js-and-sencha-touch-app/  
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 class="MsoNoSpacing" style="background: #FFFF99;">
<span style="font-family: "Lucida Console"; font-size: 8.0pt;">// Save current protocol and host for parallel uploads</span></div>
<div class="MsoNoSpacing" style="background: #FFFF99;">
"font-family: &apos;Lucida Console&apos;; font-size: 8pt;"><span style="color: #000066;">var</span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;"> currentProtocol </span><span style="color: #339933; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">= </span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;">window.</span><span style="color: #660066; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">location</span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;">.</span><span style="color: #660066; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">protocol</span><span style="color: #339933; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">;</span></div>
<div class="MsoNoSpacing" style="background: #FFFF99;">
"font-family: &apos;Lucida Console&apos;; font-size: 8pt;"><span style="color: #000066;">var</span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;"> currentHostandPort </span><span style="color: #339933; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">=</span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;"> window.</span><span style="color: #660066; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">location</span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;">.</span><span style="color: #660066; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">host</span><span style="color: #339933; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">;</span></div>
<div class="MsoNoSpacing" style="background: #FFFF99;">
"font-family: &apos;Lucida Console&apos;; font-size: 8pt;"><span style="color: #000066;">var</span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;"> currentLocation </span><span style="color: #339933; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">= </span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;">currentProtocol </span><span style="color: #339933; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">+</span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;"> </span><span style="color: #3366cc; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">"//"</span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;"> </span><span style="color: #339933; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">+</span><span style="font-family: &apos;Lucida Console&apos;; font-size: 8pt;"> currentHostandPort</span><span style="color: #339933; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">;</span></div>
<span style="font-family: "Calibri","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 style="font-family: "Calibri","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 style="color: #006600; mso-bidi-font-style: italic;"><o:p></o:p></span>
<span style="font-family: "Calibri","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 style="background-color: #ffff99; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">// Send and upload message to the webworker</span>
"background-color: #ffff99; font-family: &apos;Lucida Console&apos;; font-size: 8pt;"><span style="color: #000066;">case</span><span style="background-color: #ffff99; font-family: &apos;Lucida Console&apos;; font-size: 8pt;"> </span><span style="background-color: #ffff99; color: #3366cc; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">&apos;upload&apos;</span><span style="background-color: #ffff99; color: #339933; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">:</span>
<span style="background-color: #ffff99; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">// </span><span style="background-color: #ffff99; font-family: &apos;Lucida Console&apos;; font-size: 8pt;">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 资源库上找到

  原文地址:http://www.codeproject.com/Articles/835554/Gigabit-File-uploads-Over-HTTP-The-Node-js-version

QQ群:凯发娱乐官网官方群(515171538),验证音讯:10000
微信群:加小编微信 849023636 邀请您参加,验证音讯:10000
提示:更多精彩内容重视微信大众号:全栈开发者中心(fsder-com)
188bet uedbet 威廉希尔 明升 bwin 明升88 bodog bwin 明升m88.com 18luck 188bet unibet unibet Ladbrokes Ladbrokes casino m88明升 明升 明升 m88.com 188bet m88 明陞 uedbet赫塔菲官网 365bet官网 m88 help
网友谈论(共4条谈论) 正在载入谈论......
沉着谈论文明上网,回绝歹意咒骂 宣布谈论 / 共4条谈论
登录会员中心