js多文件切片上传 (vue项目)

问题背景

项目在移动端因为图片过大,需要进行切片上传处理。(仅涉及前端逻辑)

判断是否断网

/* 主要解决缓存了当前页面之后 用户断网再上传图片出现的逻辑错误*/
if ( navigator.onLine ) {
    
    
   //正常工作
} else {
    
    
  //执行离线状态时的任务
}
单文件上传模拟进度条
    animatePress(obj) {
    
    
      let randNum = this.getRandomNum(80, 95);
      var setIntVal = setInterval(() => {
    
    
        if (obj.press < randNum) {
    
    
          if (obj.press < 20) {
    
    
            obj.press++;
          } else {
    
    
            obj.press += 3;
          }
        }
        if (obj.press == 100) {
    
    
          clearInterval(setIntVal);
        }
      }, 100);
    },

单文件 获得一个 x- y 之间的随机数

getRandomNum(min, max) {
    
    
      let range = max - min;
      let rand = Math.random();
      return min + Math.round(rand * range);
    },

图片上传转base64

https://blog.csdn.net/lhjllff12345/article/details/72842384


$("#img_upload_file").change(function() {
    
    
        var file = this.files[0];
        var reader = new FileReader();
        reader.readAsDataURL(file);//调用自带方法进行转换
        reader.onload = function(e) {
    
    
            $("#img_upload_show").attr("src", this.result);//将转换后的编码存入src完成预览
            $("#img_upload_base").val(this.result);//将转换后的编码保存到input供后台使用
        }; 
    });

怎么获取文件数据

// capture 相机属性  multiple 多选文件 
<input type="file" accept="image/*" capture="camera" multiple="multiple" id="take-photo" @change="takePhoto">
<input type="file" accept="image/*"  multiple="multiple" id="take-photo" @change="takePhoto">
<script>
takePhoto: function(e) {
    
    
      console.log(e.target.files.length)
},
</script>

js判断文件类型、文件大小

https://blog.csdn.net/lin857/article/details/52873351

const name = files.name;
const nameType = name.substring(name.lastIndexOf('.')+1).toUpperCase();;
console.log(nameType);
if( nameType != 'JPG' && nameType != 'JPEG' && nameType != 'PNG' ){
    
    
    alert('图片类型出错')
}
if (file.size > 1024 * 10 * 1024) {
    
    
     alert("图片大小不允许超过10M")
}

怎么进行本地预览展示

<img :src="getObjectURL(value.file)" :alt="value.fileid" class="img-box-src">
getObjectURL(file) {
    
    
      var url = null;
      if (window.createObjectURL != undefined) {
    
    
        // basic
        url = window.createObjectURL(file);
      } else if (window.URL != undefined) {
    
    
        // mozilla(firefox)
        url = window.URL.createObjectURL(file);
      } else if (window.webkitURL != undefined) {
    
    
        // webkit or chrome
        url = window.webkitURL.createObjectURL(file);
      }
      return url;
    },
将base64转换为文件

https://blog.csdn.net/yin13037173186/article/details/83302628

//将base64转换为blog再转为文件  兼容ios 11.4以下
    dataURLtoBlob(base64,fileName) {
    
     
        var arr = base64.split(','),
            mime = arr[0].match(/:(.*?);/)[1],
            bstr = atob(arr[1]),
            n = bstr.length,
            u8arr = new Uint8Array(n);
        while (n--) {
    
    
            u8arr[n] = bstr.charCodeAt(n);
        }
       let theBlob = new Blob([u8arr], {
    
     type: mime });
       theBlob.lastModifiedDate = new Date();
       theBlob.name = fileName;
       return theBlob;
    },
//将base64转换为文件  不兼容ios11.4以下
    dataURLtoFile(dataurl, filename) {
    
    
      var arr = dataurl.split(","),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
      while (n--) {
    
    
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], filename, {
    
     type: mime });
    },

怎么去切割图片

    // 分片上传文件
    // file,nowcount,start,end
    // 文件,目前上传次数,切片开始值,切片结束值
    axiosSliceFile(obj, nowcount, start, end) {
    
    
      var that = this;
      var sliceSize = 1024 * 1024;
      // 文件段上传
      var sizeImg = obj.file.size;
      // 第一段开始值
      var startImg = start;
      // 第一段结束值
      var endImg = end;
      // 目前上传次数
      var countImg = nowcount;
      // 总上传次数
      var sliceCount = Math.ceil(obj.file.size / sliceSize) - 1;
      // 切分片的file文件
      var dataImg = obj.file.slice(startImg, endImg);
      // 创建一个reader
      let dataImgReader = new FileReader();
      // 将图片2将转成 base64 格式
      dataImgReader.readAsDataURL(dataImg);
      dataImgReader.onloadend = function() {
    
    
      //  分片转为file文件
      var fileImg = that.dataURLtoBlob(this.result, obj.file.type);
      // // md5 分片的file文件
      // var sliceMd5File = "";
      // var reader = new FileReader();
      // reader.readAsText(dataImg);
      // reader.onload = function(e) {
    
    
      //   let bolb = e.target.result;
      //   sliceMd5File = md5(bolb);
      // };
      // 进度条加载
      that.animateSlicePress(obj, sliceCount, countImg);
      // md5 所有的文件
      let readerFile = new FileReader();
      readerFile.readAsText(obj.file);
      var md5File = "";
      readerFile.onload = function(e) {
    
    
        let bolb = e.target.result;
        md5File = md5(bolb);
        // console.log(md5File, "file的md5文件");
        var newParaMeters = {
    
    
          sliced: true,
          filename: obj.file.name,
          file: fileImg,
          md5_value: md5File,
          total_size: obj.file.size,
          slice_count: sliceCount + 1,
          slice_index: countImg,
          slice_size: endImg - startImg
        };
        console.log("正在上传" + countImg + "块切片", newParaMeters);
        let fd = new FormData();
        fd.append("sliced", newParaMeters.sliced);
        fd.append("filename", newParaMeters.filename);
        fd.append("file", newParaMeters.file);
        fd.append("md5_value", newParaMeters.md5_value);
        fd.append("total_size", newParaMeters.total_size);
        fd.append("slice_count", newParaMeters.slice_count);
        fd.append("slice_index", newParaMeters.slice_index);
        fd.append("slice_size", newParaMeters.slice_size);
        let config = {
    
    
          headers: {
    
    
            "Content-Type": "multipart/form-data"
          }
        };
        // that.axios
        //   .post(dataUrl + "enroll/pic_upload", fd, config)
        requestUpFile(fd, config)
          .then(res => {
    
    
            // console.log(res, "多文件上传请求成功");
            // 该文件已经上传过了
            if (res.data.code == 2003) {
    
    
              that.$vux.toast.show({
    
    
                text: "系统已过滤重复作品",
                time: 1000,
                type: "cancel"
              });
              let upObjT = {
    
    
                picture_id: res.data.data.picture_id,
                path: res.data.data.picture_url,
                file: obj.file
              };
              that.animateSuccess(obj, upObjT, true);
            }
            // 整个文件上传完成
            if (res.data.code == 2001) {
    
    
              let upObjT = {
    
    
                picture_id: res.data.data.picture_id,
                path: res.data.data.picture_url,
                file: obj.file
              };
              that.animateSuccess(obj, upObjT, false);
            }
            // 切片上传完成
            if (res.data.code == 2002) {
    
    
              countImg++;
              if (countImg <= sliceCount) {
    
    
                startImg = endImg;
                if (sliceCount - countImg < 1) {
    
    
                  endImg = sizeImg;
                } else {
    
    
                  endImg += sliceSize;
                }
                that.axiosSliceFile(obj, countImg, startImg, endImg);
              }
              that.animateSlicePress(obj, sliceCount, countImg);
            }
            // 上传进度错误
            if (res.data.code == 2004) {
    
    
              countImg = parseInt(res.data.data.finished_index) + 1;
              startImg = countImg * sliceSize;
              if (sliceCount - countImg < 1) {
    
    
                endImg = sizeImg;
              } else {
    
    
                endImg += sliceSize;
              }
              // console.log(obj, countImg, startImg, endImg);
              that.axiosSliceFile(obj, countImg, startImg, endImg);
              that.animateSlicePress(obj, sliceCount, countImg);
            }
            // 上传出错
            if (res.data.code == 4001) {
    
    
              console.log(res.data,'上传出错4001');
              obj.reUpload = true;
            }
          })
          .catch(res => {
    
    
            // 请求出错
            obj.reUpload = true;
          });
        };
     }
    },

推荐阅读:
https://www.cnblogs.com/conglvse/p/9524452.html
https://blog.csdn.net/haohao123nana/article/details/51279098
https://blog.csdn.net/qq_42245281/article/details/81263303
https://www.cnblogs.com/XuYuFan/p/10209277.html
https://www.cnblogs.com/hello-word1/archive/2016/03/09/5259064.html
https://segmentfault.com/a/1190000009448892?utm_source=tag-newest

猜你喜欢

转载自blog.csdn.net/qq_15238979/article/details/88779838