我的需求:我的需求可以简单描述为,对一个大文件进行分片切割上传。我实现的思路为,对一个大文件,按照设定的chunksSize切分为N=file.size/chunkSize块,然后循环创建N个读流读取每个分片的内容,然后发起N个http.request的Post请求去上传文件。代码如下(说明:upload函数用来根据分块的个数n,计算每块起始标志位和终止标识位,并调用senddataPromise函数对每片进行操作)functionupload(username,filepath,file_id,filelength,n,alreadychunks,chunkSize){returnnewPromise(function(resolve,reject){varstart=0,end=0;varpromiseall=[];for(letcurindex=0;curindexif(filelength-start<=chunkSize){ end=filelength-1;}else{end=start+chunkSize-1;//因读取时包含start和end位}if(alreadychunks.indexOf(curindex)==-1){letoptions={flags:'r',highWaterMark:chunkSize,start:start,end:end};promiseall.push(senddataPromise(filepath,options,username,file_id,curindex,end-start+1));}start=end+1;}lettimer=setInterval(()=>{if(promiseall.length==n){clearInterval(timer);Promise.all(promiseall).then(values=>{console.log(values);console.log("alldone");resolve(true)}).catch(err=>{console.log(err);reject(err);})}},500)})}senddataPromise函数是对第i块分片创建读流读取内容,并调用doapost函数发送到后端functionsenddataPromise(path,options,username,summary,curindex,length){returnnewPromise(function(resolve,reject){letreadSteam=fs.createReadStream(path,options);readSteam.on("data",(chunk)=>{console.log("第"+curindex+"块JSON开始")letchunkjson=JSON.stringify(chunk);console.log("第"+curindex+"块JSON结束")lettempcell={data:chunkjson,n:curindex,file_id:summary,username:username,length:length};chunk=null;chunkjson=null;doapost(tempcell).then(values=>{resolve(values)}).catch(err=>{reject(err);});})})}doapost函数发起post请求发送分片数据functiondoapost(data){returnnewPromise(function(resolve,reject){leti=data.n;console.log("第"+i+"份请求准备发出")letcontents=queryString.stringify(data);data=null;letoptions={host:"localhost",path:"/nodepost/",port:8000,method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded','Content-Length':contents.length}};letreq=http.request(options,function(res){console.log("第"+i+"份请求返回数据")res.on("data",function(chunk){console.log(chunk.toString());});res.on("end",function(d){resolve("end");});res.on("error",function(e){reject(e);})});req.write(contents);req.end();contents=null;console.log("第"+i+"份请求已发出")})}我的问题:按照正常的思路,因为读取文件内容为异步操作,后面发送请求也为异步操作,所以也就是说会出现对于n个分片,读取数据已经读取了p片,并且已经有q(**q已经完成上传完成返回数据的情况,但是现在问题是,***发现并没有分片上传完返回数据的
情况出现,都是在n个分片读取完成后,才开始统一执行分片内容上传操作***图片如下:(由于图片无法上传,我把程序运输出拷贝一下){kind:'upload',username:'moran999',filepath:'F:/my_upload_test/NowTest.pdf',file_id:'-196987878-472217752177633040957425519',alreadychunks:[],chunkSize:1048576,n:9}第0块JSON开始第0块JSON结束第0份请求准备发出第0份请求已发出第1块JSON开始第1块JSON结束第1份请求准备发出第1份请求已发出第2块JSON开始第2块JSON结束第2份请求准备发出第2份请求已发出第3块JSON开始第3块JSON结束第3份请求准备发出第3份请求已发出第5块JSON开始第5块JSON结束第5份请求准备发出第5份请求已发出第4块JSON开始第4块JSON结束第4份请求准备发出第4份请求已发出第6块JSON开始第6块JSON结束第6份请求准备发出第6份请求已发出第8块JSON开始第8块JSON结束第8份请求准备发出第8份请求已发出第7块JSON开始第7块JSON结束第7份请求准备发出第7份请求已发出第8份请求返回数据moran999第4份请求返回数据moran999第6份请求返回数据moran999第1份请求返回数据moran999第2份请求返回数据moran999第0份请求返回数据moran999第3份请求返回数据moran999第7份请求返回数据moran999第5份请求返回数据moran999['end','end','end','end','end','end','end','end','end']alldone可以看到其POST数据的发出并不是和读流无关的,即任何一个POST都不会发出,直到到所有的读流读取完数据,想问一下各位码友是什么原因尼??因为正常理解下当第i个读流读的时候,前面已经读取完内容的读流完全可以进行post操作了啊,但实际上并没有。之所以会问这个问题是因为当我输入的文件比较大时,他执行到《第12块JSON开始时,就内存溢出了》,而如果程序是post不用等待所有的读流读完时,当有一部分post执行完之后,其对应的数据就被回收了,释放相应的内存,就不会出现内存溢出了。
噜噜哒
相关分类