很多时候我们都会用到大文件的上传,但是如果单一的上传会很慢,前端将2M发送一个请求,然后传给后台,后台将其拼接起来,当最后一个都传完,后台拼接存起来,返回我们所需要的路径

首先创建一个js文件

class fileUpload {
  constructor(serviceUrl) {
    this._serviceUrl = serviceUrl;
    // this._bid = BID;
    // this._fieldName = fieldName;
    this._indexArr = [];
    this._file;
    this._name;
    this._size;
    this._shardSize = 2 * 1024 * 1024;
    this._shardCount;
    this._group = 0;
    this._start = 0;
    this._end;
    this._fileSucess = false;
    this.percentage = 0;
    this._groupSize = 50;
    this.successUpload = null;
    this.percentageSend = null;
    this._sendFile = {}; //保存整条数据时传给后台的数据
  }
  //单文件上传
  upLoad(onefile) {
    //初始化数据
    this._group = 0;
    this._start = 0;
    this._end = 0;
    this.percentage = 0; //进度
    this._indexArr = [];
    this._fileSucess = false;
    this._file = onefile;
    this._name = this._file.name; //文件名
    this._size = this._file.size; //总大小
    this._shardSize = 2 * 1024 * 1024; //以2MB为一个分片
    this._shardCount = Math.ceil(this._size / this._shardSize); //总片数
    this._uploadByCel(this._group * this._groupSize);//
  }
  //多分片时,每次只派发50个分片
  _uploadByCel(startIndex) {

    //本次循环将发出去的结尾block数;
    let cCount = Math.min(this._shardCount, (this._group + 1) * this._groupSize);//总片数和50比较cCount取小的值
    const nowtime=this.formatTime(new Date())
    for (let i = startIndex; i < cCount; i++) {
      this._start = i * this._shardSize;
      this._end = Math.min(this._size, this._start + this._shardSize);//结束时总大小,和 开始的大小+之前的大小比较
      let form = new FormData();//new一个form的实例,可以进行键值对的添加,
      let request = new XMLHttpRequest()
      //对form进行添加,form.get('data'),可以通过get方法获取到值
      console.log(this._file.lastModified,"this._filethis._filethis._filethis._file")
      form.append("data", this._file.slice(this._start, this._end)); //slice方法用于切出文件的一部分
      form.append("name", this._name);
      form.append("total", this._shardCount); //总片数
      form.append("index", i + 1);
      form.append("nowtime", this._file.lastModified);
      form.get('nowtime')
      form = this.initHttpHeader(form);

      // form.append("folderid", this._bid);
      // form.append("fieldname", this._fieldName);
      if (request && form) {
        request.open("POST", this._serviceUrl, true);
        request.onload = (oEvent) => {
          let aaa = JSON.parse(request.response);
          let obj = aaa.data
          if (obj && obj.end) {
            this._fileSucess = true;
            this.percentage = 100;
            //构造保存数据时传给后台的数据
            // if (obj.folderid)
            //   this._sendFile.folderid = obj.folderid;
            // if (obj.foldername)
            //   this._sendFile.foldername = obj.foldername;
            if (obj.name)
              this._sendFile.name = obj.name;
            if (obj.fileid)
              this._sendFile.fileid = obj.fileid;
            if (obj.realname)
              this._sendFile.realname = obj.realname;
            // if (obj.fieldname)
            //   this._sendFile.fieldname = obj.fieldname;
            if (this.percentageSend != null)
              this.percentageSend(this.percentage);
            if (this.successUpload != null)
              this.successUpload(true, this._sendFile,obj);
          } else
            if (this.successUpload != null)
              this.successUpload(false);
          if (obj && obj.index && obj.name != 'null' && obj.state && !obj.end) {
            this._indexArr.push(obj.index);
            this.percentage = Math.floor((this._indexArr.length / this._shardCount) * 100);
            if (this.percentageSend != null)
              this.percentageSend(this.percentage);
            if (cCount != this._shardCount) {
              if (this._indexArr.length == cCount) {

                this._group++;
                this._uploadByCel(this._group * this._groupSize);
              }
            }
          }
          if (obj && obj.index && !obj.state) {
            if (!this._fileSucess)
              this._reUpload(obj.index);
          }
        };
        request.send(form);
      }
    }
    // return this.percentage;
  }
  initHttpHeader(form) {
    let out_form = form;

    //----------TODO------------
    // out_form.append("folderid", this._bid);
    // out_form.append("fieldname", this._fieldName);
    //--------------------------

    return out_form;
  }
  //上传出现问题未上传的区片重现上传
  _reUpload(index) {
    this._start = index * this._shardSize;
    this._end = Math.min(this._size, this._start + this._shardSize);
    let form = new FormData();
    let request = new XMLHttpRequest()
    //append在form中元素的尾部添加内容
    form.append("data", this._file.slice(this._start, this._end)); //slice方法用于切出文件的一部分
    form.append("name", this._name);
    form.append("total", data.length); //总片数
    form.append("index", index);
    form = this.initHttpHeader(form);

    // form.append("folderid", this._bid);
    // form.append("fieldname", this._fieldName);
    if (request && form) {
      request.open("POST", this._serviceUrl, true);
      request.onload = (oEvent) => {
        let obj = JSON.parse(request.response);
        if (obj && obj.end) {
          this._fileSucess = true;
        }
        if (obj && obj.index && obj.name != 'null' && obj.state) {
          this._indexArr.push(obj.index);
          this.percentage = Math.floor((this._indexArr.length / this._shardCount) * 100);
        }
      };
      request.send(form);
    }
  }
  formatTime(time, type, doubleNum) {
    /**time:需要转换的时间;
     * type:需要格式化的类型y(y)、y-m(m)、y-m-d(d)/y-m-d h:m:s(默认);
     * doubleNum:月日时分秒的类型,例如2017-6('1') or 2017-06(默认)**/
      let mydate = time ? new Date(time) : new Date();
      let year = mydate.getFullYear();
      let month = mydate.getMonth() + 1;
      let day = mydate.getDate();
      let hour = mydate.getHours();
      let minute = mydate.getMinutes();
      let second = mydate.getSeconds();
      if (!doubleNum) {
          month = month < 10 ? '0' + month : month;
          day = day < 10 ? '0' + day : day;
          hour = hour < 10 ? '0' + hour : hour;
          minute = minute < 10 ? '0' + minute : minute;
          second = second < 10 ? '0' + second : second;
      }
      if (type == 'y') {
          return year;
      } else if (type == "m") {
          return year + '-' + month;
      } else if (type == 'd') {
          return year + '-' + month + '-' + day;
      } else {
          return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ":" + second;
      }
  }
}
export default fileUpload;

这个是一个vue, 

<template>
    <div class="fileuploadbase">
        <div class="fileuploadgroup">
            <input type="file" name="file" id="fileinput" @change="fileUploadChanged" :multiple='false' style="display: none;" />
            <el-button @click="fileButtonClick()" :disabled="!isUploadClick || (state!='ADD'&&state!='EDIT')" icon="el-icon-upload" size="mini" plain style='width"96px;height:38px;font-size: 14px;'>{{fileButtonText}}</el-button>
            <div class="currentfilename" v-if="!isAutoUpload">{{ waitUploadFile }}</div>
            <el-button @click="fileUploadStartup" v-show="isFileUploadStartupBottonShow" v-if="!isAutoUpload" size="mini" plain>点击上传</el-button>
        </div>
        <div v-show="currentFileName.length > 0">
            <div class="fileuploadgroup" v-for="(item, index) in currentFileName" :key="index">
                <div class="currentfilename" @click="handleFileDownloadClick(item)">{{ item.name }}</div>
                <el-progress :text-inside="true" :stroke-width="18" :percentage="percentage" class="elprogress" v-show="isProgressVis && index==(currentFileName.length-1)"></el-progress>
                <i class="el-icon-delete" title="删除文件" @click="handleFileDelClick(item)" v-show="isDeleteIconShow && (!isProgressVis || index!=(currentFileName.length-1)) && (state=='ADD'||state=='EDIT')" :style="{cursor: 'pointer'}"></i>
            </div>
        </div>
    </div>
</template>
<script>
// import fileUpload from "./file-upload.js"
import fileUpload from "../../../../static/js/file-upload.js"
export default {
    name: "file-upload",
    data() {
        return {
            percentage: 0,
            filesdata: [],  // 
            fileUpload,
            isDeleteIconShow: false,
            isFileUploadStartupBottonShow: false,
            isProgressVis: false,
            currentFileName: [],
            waitUploadFile: "",
            isUploadClick: true
        }
    },
    props: {
        // 上传方式:true - 自动上传;false - 手动上传
        isAutoUpload: {
            type: String,
            default: true,
        },
        // 单/多文件:true - 多文件;false - 单文件
        isMultiple: {
            type: String,
            default: false,
        },
        // 状态:ADD - 新建;READ - 查看;EDIT - 修改
        state: {
            type: String,
            default: null,
        },
        // 上传服务地址
        fileUploadURL: {
            type: String,
            default: null,
        },
        // 已有附件集合
        histFileArr: {
            type: Array,
            default: [],
        }
    },
    computed: {
        fileButtonText() {
            if (this.currentFileName.length == 0) {
                return '上传数据';
            } else {
                return '继续添加';
            }
        }
    },
    methods: {
        fileUploadChanged() {
            this.filesdata = this.$el.getElementsByTagName("input")[0].files;//this.$el.getElementsByTagName方法可返回带有指定标签名的对象的集合。
            if (this.filesdata.length == 0) return;
            this.isDeleteIconShow = true;
            this.isFileUploadStartupBottonShow = true;
            this.isProgressVis = false;
            this.percentage = 0;
            this.waitUploadFile = this.filesdata[0].name;
            if (this.isAutoUpload) {
                this.fileUploadStartup();
            }
        },
        fileUploadStartup() {
            this.isUploadClick = false;
            this.isDeleteIconShow = false;
            this.isFileUploadStartupBottonShow = false;
            if (!this.isMultiple) {
                this.fileDelOper(this.currentFileName[0]);// 进行删除操作
                this.currentFileName = [];
            }
            this.isProgressVis = true;
            this.currentFileName.push({ name: this.filesdata[0].name });
            this.fileUpload = new fileUpload(this.fileUploadURL);
            console.log(this.filesdata[0],"this.filesdata[0]")
            this.fileUpload.upLoad(this.filesdata[0],this.formatTime(new Date()));
            this.fileUpload.percentageSend = this.percentageSend;
            this.fileUpload.successUpload = this.successUpload;
        },
        //接收上传的百分值回调
        percentageSend(perNum) {
            this.percentage = perNum;
        },
        successUpload(success, field,value) {
            if (success) {
                if (this.percentage < 100) return;
                this.isDeleteIconShow = true;
                this.isFileUploadStartupBottonShow = false;
                this.isProgressVis = false;
                this.isUploadClick = true;
                document.getElementById("fileinput").value = "";
                this.waitUploadFile = "";
                this.successvalue=value
                this.$emit('successvalue',this.successvalue);   
                this.$message({
                    message: '文件上传成功',
                    type: 'success'
                });
            }

        },
        // 点击文件后面的删除按钮
        handleFileDelClick(item) {
            this.filesdata = [];
            document.getElementById("fileinput").value = "";
            for (let i = 0; i < this.currentFileName.length; i++) {
                if (this.currentFileName[i].name == item.name) {
                    this.fileDelOper(item);// 进行删除操作
                    this.currentFileName.splice(i, 1); //删除下标为i的元素
                    return this.currentFileName;
                }
            }
            this.isDeleteIconShow = false;
            this.isFileUploadStartupBottonShow = false;
            this.isProgressVis = false;
        },
        // 点击选取文件
        fileButtonClick() {
            document.getElementById('fileinput').click();
        },
        // 删除操作
        fileDelOper(val) {
            this.$emit("fileDelOper", val);
        },
        // 点击文件下载
        handleFileDownloadClick(val) {
            this.$emit("fileDownload",val);
        }
    },
    watch: {
        histFileArr() {
            if (!this.histFileArr) {
                this.isDeleteIconShow = false;
                this.currentFileName = [];
                return;
            }
            this.isDeleteIconShow = true;
            this.currentFileName = this.histFileArr;
        }
    },
    created() {
        if (!this.histFileArr) {
            this.isDeleteIconShow = false;
            this.currentFileName = [];
            return;
        }
        this.isDeleteIconShow = true;
        this.currentFileName = this.histFileArr;
    }
}
</script>
<style scoped>
a {
    color: #42b983;
}
</style>

只要引进这两个然后就写页面,在template中

<template>
  <div class="new_con">
    <el-card class="box-card">
      <el-form
        :model="sjgxform"
        class="form_protocol"
        label-position="right"
        style="margin:0 auto;width:80%"
      >
        <el-form-item label="大文件上传" style="text-align: left;">
          <div class="hello"  style="width:75%;margin-left:27px;display: inline-block;">
            <div class="operbuttongroup" >
              <file-upload
                isAutoUpload="true"
                isMultiple="false"
                state="ADD"
                :fileUploadURL="fileUploadURL"
                :histFileArr="histFileArr"
                @fileDelOper="fileDelOper"
                @fileDownload="fileDownload"
                @successvalue='successvalue'
              ></file-upload>
            </div>
          </div>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>
<script>
import FileUpload from "../../components/bigfiles.vue";
export default {
  components: {
    FileUpload
  },
  computed: {
  },
  data() {
    return {
      

      //大文件上传
      fileUploadURL: window.bigupload, // 上传服务地址
      histFileArr: [] // 已有附件集合
    };
  },

  watch: {
  },
  methods: {
    

    
    //大文件上传
    fileDelOper(val) {},
    fileDownload(val) {},
    successvalue(val) {
      console.log(val,"大文件上传成功了,然后就可以看到返回的值了")
      this.sjgxform.fjList.push({
        PID: this.$route.query.id,
        WDFL: "3",
        WDMC: val.WDMC,
        WJLJ: val.WJLJ,
        CJRID: this.$store.state.Login.userInfo.ID
      });

    }
  },
  mounted() {
   
  }
};
</script>
<style scoped>

 

 

Logo

前往低代码交流专区

更多推荐