大文件上传和断点续传

1.解决思路:将大文件分割成n份 ,断点续传就是每次发送前都查询下服务器是否有未传的碎片

2.设计相关主要api:
   Blob.slice:返回文件碎片

  服务端API:

   fs.appendFileSync:将单个文件合并到一个文件里
 

test.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <script type="application/javascript">
        let globalFileObj = [];
        let divideLength = 1;
        function request(options){
            return new Promise(function(resolve , reject){
                let xhr = new XMLHttpRequest()
                xhr.open('POST',options.url)
                xhr.send(options.data)
                xhr.onload = function(res){
                    resolve(res.target.response)
                }
            })
        }
        function uploadFile(e){
            let filea = document.getElementById('file')
            let file = filea.files[0]
            let ceil = Math.ceil(file.size/divideLength)
            let position = 0
            while(position < file.size){
                globalFileObj.push({file:file.slice(position , position+ceil)})
                position += ceil
            }
            let requestCount = globalFileObj.length
            globalFileObj.map(function(item , index){
                let formData = new FormData()
                formData.append('chunk' , item.file)
                formData.append('name' , 'xxx'+index)
                request({url:'http://localhost:3000' , data:formData}).then(function(){
                    requestCount-=1
                }).catch(function(e){console.log(e)})
            })
            let interval = setInterval(function(){
                if(requestCount<=0){
                    clearInterval(interval)
                    console.log('all file upload')
                }
            },30)
        }
    </script>
    <body>
        <input type="file" onChange="uploadFile()" id="file" />
    </body>
</html>

 

 

server.js:需要安装依赖fs-extra multiparty

 

const http = require("http");
const path = require("path");
const fse = require("fs-extra");
const multiparty = require("multiparty");

const server = http.createServer();
 const UPLOAD_DIR = path.resolve(__dirname, "..", "file"); // 大文件存储目录

server.on("request", async (req, res) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader("Access-Control-Allow-Headers", "*");
  
  if (req.method === "OPTIONS") {
    res.status = 200;
    res.end();
    return;
  }

  const multipart = new multiparty.Form();

  multipart.parse(req, async (err, fields, files) => {
      console.log('receive request ',fields)
    if (err) {
      return;
    }
    // const [hash] = fields.hash;
    const [name] = fields.name;
    const chunkDir = `${UPLOAD_DIR}/${name}`;

   // 切片目录不存在,创建切片目录
   console.log('chunkDir = '+chunkDir)
   console.log('chunk.path = '+chunk.path)
    if (!fse.existsSync(chunkDir)) {
      fse.mkdirs(chunkDir).then(function(){
          fse.move(chunk.path, chunkDir);
      }).catch(function(){})
    }else{
        fse.move(chunk.path, chunkDir);
    }
    res.end("received file chunk");
  });
});

server.listen(3000, () => console.log("文件服务器端口监听在30000"));

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页