js + node 分片上传

首先是HTML5的几个规范

  • File
  • FileReader
  • ArrayBuffer
  • Blob

input上传的文件就是File类型文件,而File是基于Blob设计的。

接口自带slice方法,可以分割文件,达到分片上传的目的。

FileReader可以读取Blob里面的内容。

//将字符串转换成 Blob对象
var blob = new Blob(['中文字符串'], {
    type: 'text/plain'
});
//将Blob 对象转换成字符串
var reader = new FileReader();
reader.readAsText(blob, 'utf-8');
reader.onload = function (e) {
    console.info(reader.result);
}

把上传文件接口类型设定为multipart/form-data,然后上传经过slice分片的文件。

var file = document.getElementById('upload').file;
var form = new FormData();
var startSize = 0;
var chunkSize = 5242880; //每次分割5M
form.append('file',file.slice(startSize,startSize+chunkSize));
  startSize+=chunkSize;
xhr.open('post', '/upload', true);
xhr.send(form);

node里可以用中间件解析文件,比如formidable、multer

const formidable = require('formidable');

app.use(formidable (
   {
      encoding: 'utf-8',
      multiples: true, // req.files to be arrays of files
   }
));

接口里可以用可读取流fs.createReadStream、读写文件操作文件,代码如下。

var fileInfo,
   fileReceive;

app.post('/upload',function (req, res) {
   console.log('files',req.files);
      var file = req.files.file;
      if(file && fileInfo.end < fileInfo.size){
         fs.readFile(file.path,(err,data)=>{
            if(err){
               return console.error(err);
            };
            fileReceive = fileReceive ? Buffer.concat([fileReceive,data]) : data;
            fileInfo.end += data.length;

            if(fileInfo.end >= fileInfo.size){
               fs.writeFile(fileInfo.name,fileReceive,()=>{
                  console.log('上传完成!');
               });
            };
            res.send({progress: fileInfo.end / fileInfo.size});
         });
      }else{
         res.send('error');
      }
 });

先获取文件总大小、文件名字等信息,然后每次接受到分片文件后对buffer进行合并并且保存已经接受到的文件大小,当接受完成后保存文件。

注这个方法需要node可操作的内存大于接受文件,否则就要每次接受分片文件时都读写一遍文件,不再node里进行缓存,但是这样比较费时。

猜你喜欢

转载自www.cnblogs.com/ksyy/p/11526340.html