使用Node.js合并文件碎片时出现标题的错误信息。代码分析m.merge=(opts)=>{returnnewPromise((resolve,reject)=>{const{filename,target}=opts;try{letlen=0;constbufferList=fs.readdirSync(`${STATIC_TEMPORARY}/${filename}`).map((hash,index)=>{constbuffer=fs.readFileSync(`${STATIC_TEMPORARY}/${filename}/${index}`);len+=buffer.length;returnbuffer;});//合并文件constbuffer=Buffer.concat(bufferList,len);constws=fs.createWriteStream(`${target}/${filename}`);ws.write(buffer);ws.close();resolve({success:true,msg:'Sectionmergecompleted'});}catch(error){console.error(error);reject({success:false,msg:error}});}});};constbuffer=Buffer.concat(bufferList,len);定位到上面那行有问题,查看服务器,node应用内存占用192.1mb。这时候,道理就很清楚了。是因为文件碎片太大导致内存耗尽,没有可用空间。优化方法上面的方法是concat所有的文件分片,写入stream。正是在这个过程中,内存被耗尽。其实我们可以按顺序多次写concat,修改代码如下:m.merge=(opts)=>{returnnewPromise((resolve,reject)=>{const{filename,target}=opts;try{//优化constws=fs.createWriteStream(`${target}/${filename}`);constbufferList=fs.readdirSync(`${STATIC_TEMPORARY}/${filename}`)letlen=0;letlist=[]bufferList.forEach((hash,index)=>{constb=fs.readFileSync(`${STATIC_TEMPORARY}/${filename}/${index}`);len+=b.length;list.push(b)if(len>10485760){//10Mconstbuffer=Buffer.concat(list,len);ws.write(buffer);len=0;list=[]}})ws.close();resolve({success:true,msg:'Sectionmergecompleted'});}catch(error){console.error(error);reject({success:false,msg:error});}});};这是重新调用接口时标题不会报错,文件可以合并成功。但是查看Node进程的内存使用情况,仍然保持在192.1mb左右。如果进一步分析,上面的代码还是有点啰嗦,试试下面的:m.merge=(opts)=>{returnnewPromise((resolve,reject)=>{const{filename,target}=opts;try{//优化constws=fs.createWriteStream(`${target}/${filename}`);constbufferList=fs.readdirSync(`${STATIC_TEMPORARY}/${filename}`)bufferList.forEach((hash,index)=>{constb=fs.readFileSync(`${STATIC_TEMPORARY}/${filename}/${index}`);ws.write(b);})ws.close();resolve({success:true,msg:'Sectionmergecompleted'});}catch(error){console.error(error);reject({success:false,msg:error});}});};文件写入到ws中,因为文件大小已经被分成1M块,每次读写ws后,都会被Node.jsGC回收,理论上是比较安全的操作。修改后,经过测试,发现只有上传文件和分片合并时,内存占用200M左右,CPU消耗高,合并完成后趋于稳定。总结通过一个RangeError:Arraybufferallocationfailed的错误,我们认识到了合理使用内存的重要性。解决这个问题后,我们的大文件分段上传功能运行更稳定了。如果你遇到过这样的问题,希望这篇文章能帮到你,还请给我一个赞????,谢谢。如果大家有更好的方法,欢迎在评论区讨论。文章首发于IICOOM-个人博客《RangeError: Array buffer allocation failed》
