基于element UI 实现大文件分片上传

这篇具有很好参考价值的文章主要介绍了基于element UI 实现大文件分片上传。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

将文件进行切片,上传至服务器,上传完成后通知服务器进行合并

屏幕录制2022-11-11 16.40.06文章来源地址https://www.toymoban.com/news/detail-427417.html

  • 测试用例
<template>
  <div name="test-upload-img">
    <s-upload-img v-model="logo"></s-upload-img>
  </div>
</template>

<script>
export default {
  name: "test-upload-img",
  extends: {},
  mixins: [],
  components: {},
  emits: [],
  props: {},
  data() {
    return {
      logo: "zfs/2022-11-11/0ae8e4f733fe4bbdbb00f92fb1247273.jpeg"
    }
  },
  created() {
  },
  methods: {}
}
</script>	
  • s-upload
<script>
import {getMinioUrl} from "../../../static/global.util";

export default {
  name: "s-upload",
  extends: {mixins: []},
  components: {},
  emits: [],
  model: {},
  props: {
    value: {type: [String, Array]}, // v-model 绑定的Object
    limit: {type: Number, default: 1}, // 控制 上传图片数量
    accept: {type: String, default: undefined}, // 限制上传的文件类型
  },
  data() {
    return {
      fileList: [],
      chunkSize: 1024 * 1024 * 6, // 6M 为一个切片,超过6M,则采用上传大文件的方法进行文件上传
      percentage: {}, // 进度条
    }
  },
  computed: {
    action: {
      get() {
        return this.$getRequestUrl(this.$servers.openServer, 'tb/minio/uploadImgCompress')
      }
    },
    previewImgs: {
      get() {
        return this.fileList.map(o => getMinioUrl(o.url));
      },
    },
    hide: {
      get() {
        return this.fileList.length === this.limit;
      }
    }
  },
  watch: {},
  created() {
    this.fileList = (
        this.value
            ? this.limit === 1 ? [{url: this.value}] : (this.value instanceof Array ? this.value : JSON.parse(this.value)).map(o => ({url: o}))
            : []
    ).filter(o => o.url).map(({url}) => ({url, name: url.slice(url.lastIndexOf('/') + 1)})).map(o => ({...o, uid: o.name}));
  },
  methods: {
    getMinioUrl,
    onSuccess(res, file, fileList) {
      this.fileList = fileList;
      let imgs = this.limit === 1
          ? res.data.visitPath
          : JSON.stringify(fileList.map(img => img.response ? img.response.data.visitPath : img.url))
      console.log(imgs)
      this.$emit('input', imgs);
    },
    handleRemove(file) {
      this.fileList.splice(this.fileList.indexOf(file), 1)
      let imgs = this.limit === 1
          ? this.fileList.length <= 0
              ? ''
              : this.fileList.length === 1 && this.fileList[0].response
                  ? this.fileList[0].response.data.visitPath
                  : this.fileList[0].url
          : JSON.stringify(this.fileList.map(img => img.response ? img.response.data.visitPath : img.url))
      this.$emit('input', imgs);
    },
    httpRequest(params) {
      let {file: {size}} = params;
      size > this.chunkSize ? this.uploadBigFile(params, this.chunkSize) : this.uploadFile(params)
    },
    uploadFile(params) {
      let {file, filename, onSuccess} = params;
      const formData = new FormData();
      formData.append(filename, file);
      const config = {
        'Content-type': 'multipart/form-data',
        onUploadProgress: progress => this.percentage = Math.floor(progress.loaded / progress.total * 100)
      }
      this.$post(this.$servers.openServer, 'tb/minio/upload', formData, config).then(onSuccess)
    },
    calculationPercentage(file, index, loadeds, size) {
      const loaded = loadeds.filter(o => o.length > 0).map(o => o[o.length - 1]).reduce((prev, curr) => prev + curr)
      this.$set(this.percentage, file.uid, Math.floor(loaded / size * 100))
    },
    uploadBigFile(params, chunkSize) {
      let {file, filename, onSuccess} = params;
      let {size, type, name} = file;
      const chunkLength = Math.ceil(file.size / chunkSize)
      let chunks = Array.from({length: chunkLength}).map((v, i) => file.slice(i * chunkSize, i * chunkSize + chunkSize))
      let loadeds = [];
      let chunkRequests = chunks.map((chunk, i) => {
        const formData = new FormData();
        formData.append(filename, chunk);
        loadeds[i] = [];
        const config = {
          'Content-type': 'multipart/form-data',
          onUploadProgress: progress => {
            loadeds[i].push(progress.loaded)
            this.calculationPercentage(file, i, loadeds, size);
          }
        }
        return this.$post(this.$servers.openServer, 'tb/minio/upload', formData, config);
      })
      this.$axios.all(chunkRequests).then(res => {
        let fileNames = res.map(({data: {minioPath}}) => minioPath)
        const params = {fileName: name, contentType: type, fileSize: size, fileNames}
        this.$post(this.$servers.openServer, 'tb/minio/merge', params).then(onSuccess)
      })
    },
    onRemove(file, fileList) {
      this.percentage = -1;
    }
  }
}
</script>
  • s-upload-img
<style scoped lang="less">
.hide-upload {
  /deep/ .el-upload {
    visibility: hidden;
  }
}
</style>
<template>
  <div name="s-upload-img">
    <el-upload
        :class="{'hide-upload':hide}" list-type="picture-card" v-bind="$attrs"
        :file-list="fileList" :action="action" :limit="limit" :accept="accept"
        :on-success="onSuccess" :http-request="httpRequest">
      <i slot="default" class="el-icon-plus"></i>
      <div slot="file" slot-scope="{file}">
        <el-progress v-if="percentage[file.uid] && percentage[file.uid]<100" type="circle" :percentage="percentage[file.uid]"></el-progress>
        <img :src="getMinioUrl(file.url)" style="width:100%; height:auto;" alt="">
        <span class="el-upload-list__item-actions">
          <span class="el-upload-list__item-preview" @click="()=>this.$refs.previewImg.showViewer = true">
            <i class="el-icon-zoom-in"></i>
          </span>
          <span class="el-upload-list__item-delete" @click="handleRemove(file)">
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>
    <el-image ref="previewImg" v-show="false" src :preview-src-list='previewImgs'></el-image>
  </div>
</template>

<script>
import SUpload from "./s-upload";

export default {
  name: "s-upload-img",
  extends: SUpload,
  props: {
    accept: {type: String, default: '.jpeg,.jpg,.png'}, // 限制上传的图片类型
  },
}
</script>

到了这里,关于基于element UI 实现大文件分片上传的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包