大文件上传,文件切片、断点上传

245 阅读1分钟
  // 通过文件流来判定类型 
   async blobToString(blob){
      return new Promise(resolve=>{
        const reader = new FileReader()
        reader.onload = function(){
          console.log(reader.result)
          const ret = reader.result.split('')
                        .map(v=>v.charCodeAt())
                        .map(v=>v.toString(16).toUpperCase())
                        // .map(v=>v.padStart(2,'0'))
                        .join('')
          resolve(ret)
          // const ret = reader.
        }
        reader.readAsBinaryString(blob)
      })
    } ,
   // 判定是不是gif
    async isGif(file){     
      // GIF89a 和GIF87a
      // 前面6个16进制,'47 49 46 38 39 61' '47 49 46 38 37 61'
      // 16进制的转换
      const ret = await this.blobToString(file.slice(0,6))
      const isGif = (ret=='47 49 46 38 39 61') || (ret=='47 49 46 38 37 61')
      return isGif
    },
    async isPng(file){
      const ret = await this.blobToString(file.slice(0,8))
      const ispng = (ret == "89 50 4E 47 0D 0A 1A 0A")
      return ispng
    },
    async isJpg(file){
      const len = file.size
      const start = await this.blobToString(file.slice(0,2))
      const tail = await this.blobToString(file.slice(-2,len))
      const isjpg = (start=='FF D8') && (tail=='FF D9')
      return isjpg
    },
    async isImage(file){
      return await this.isGif(file) || await this.isPng(file)
    },
 //文件切片 file.slice(1000,2000);字节 
   createFileChunk(file,size=CHUNK_SIZE){
      const chunks = [] 
      let cur = 0
      while(cur<this.file.size){
        chunks.push({index:cur, file:this.file.slice(cur,cur+size)})
        cur+=size
      }
      return chunks
   },
    //计算文件的MD5值
    async calculateHashWorker(){      
return new Promise(resolve=>{        
    this.worker = new Worker('/hash.js')        
    this.worker.postMessage({chunks:this.chunks})       
    this.worker.onmessage = e=>{        
      const {progress,hash} = e.data          
        this.hashProgress = Number(progress.toFixed(2))       
       if(hash){          
          resolve(hash)        
       }     
   }     
 })    
},

  async uploadChunks(uploadedList=[]){      
    const requests = this.chunks.filter(chunk=>uploadedList.indexOf(chunk.name)==-1)
        .map((chunk,index)=>{         
 // 转成promise          const form = new FormData()          
 form.append('chunk',chunk.chunk)         
 form.append('hash',chunk.hash)          
 form.append('name',chunk.name)       
   // form.append('index',chunk.index)      
    return {form, index:chunk.index,error:0}      
  })     
   .map(({form,index})=> this.$http.post('/uploadfile',form,{  
        onUploadProgress:progress=>{   
         // 不是整体的进度条了,而是每个区块有自己的进度条,整体的进度条需要计算     
       this.chunks[index].progress = Number(((progress.loaded/progress.total)*100).toFixed(2))   
       }    
    }
))






通过Blob.slice方法,可以将大文件分片,轮循向后台提交各文件片段,即可实现文件的分片上传。