Skip to content

上传组件

xinwu-yang edited this page Mar 1, 2023 · 1 revision

介绍

支持S3标准协议,支持多线程断点续传,并提供Vue组件版和JavaScript版。超过设置分片大小的文件,自动使用分片上传,每个分片不能小于5MB,且不能超过5GB,默认为5MB。

已有功能

  • WebWorker多线程分片上传
  • 暂停上传(暂时停止上传,保留上传任务)
  • 继续上传(继续上传暂停的任务)
  • 取消上传(调用取消上传后,整个文件需要重新上传)
  • 断点续传(bucket、object与上次上传相同的话,自动触发断点续传)
  • 超时重试(3次)
  • 上传进度(status:状态,percent:进度)
  • 实时上传速度(speed:速度,element:单位)

安装

yarn add @tievd/cube-chunk-uploader -S

用法一:Vue 项目

// vue组件 ant-design
import Vue from 'vue'
import { ChunkUploader } from '@tievd/cube-chunk-uploader'

Vue.use(ChunkUploader)

// or js类
import CubeUploader from '@tievd/lib/cubeUploader'
new CubeUploader(...)

用法二:html 项目

<!-- 将安装包中的./lib/cube-chunk-uploader.min.js引入项目,样式根据自己项目实现 -->
<script type="text/javascript" src="your-path/cube-chunk-uploader.min.js"></script>
<script type="text/javascript">
  var uploader = new CubeChunkUploader(...);
</script>

ChunkUploader API(vue组件)

ChunkUploader

参数 说明 类型 默认值
config 基本配置,host(服务地址)、port(服务端口)、protocol(http:或https:)、accessKeyId、secretAccessKey、sessionToken、region object
bucket 上传桶名 string
object 上传对象 string
styleType 组件样式 'default'|'card'|'draggable' 'default'
tip 提示styleType='draggable'时有用 string
chunkSize 分片大小,单位Byte number 5 * 1024 * 1024
maxSize 最大体积,单位MB number 5 * 1024 * 1024
maxWorkerCount 最大线程数,一般为cpu逻辑核心数 number window.navigator.hardwareConcurrency
showProgress 是否展示进度条 boolean false
showSpeed 是否展示实时速度 boolean false
showLoading 是否展示loading boolean false
fileChange 文件变化的回调 function function(file)
success 上传成功的回调 function function()
progress 上传进度的回调 function function(data: { status, percent})状态、进度
speed 上传速度的回调 function function(data: {speed, element})速度、单位

refs事件

事件名称 说明
abortUpload 取消上传
pauseUpload 暂停上传
continueUpload 继续上传
doUpload 进行上传

CubeChunkUploader API(js版)

CubeChunkUploader

参数 说明 类型 默认值
config 基本配置,host(服务地址)、port(服务端口)、protocol(http:或https:)、accessKeyId、secretAccessKey、sessionToken、region、chunkSize、maxWorkerCount object
bucket 上传桶名 string
object 上传对象 string
handleComplete 上传成功的回调 function
handleUploadProgress 上传进度的回调 function
handleSpeed 上传速度的回调 function

事件

事件名 说明 参数
addFile 添加文件 function(file)
removeFile 移除文件 function(index) 文件位置
abortUpload 取消上传 function()
pauseUpload 暂停上传 function()
continueUpload 继续上传 function()
doUpload 进行上传 function()

示例一 Vue组件

<template>
  <div style="margin: 20px;">
    <chunk-uploader
      ref="chunkUploader"
      :config="config"
      :bucket="bucket"
      :object="object"
      :showSpeed="true"
      :showLoading="true"
      :showProgress="true"
      @fileChange="handleFileChange"
      @success="handleSuccess"
      @progress="handleProgress"
      @speed="handleSpeed"
    ></chunk-uploader>
    <a-button @click="doUpload">开始上传</a-button>
    <a-button style="margin-left: 15px" type="danger" @click="abortUpload">终止上传</a-button>
    <a-button style="margin-left: 10px" @click="pauseUpload">暂停上传</a-button>
    <a-button style="margin-left: 10px" type="primary" @click="continueUpload">继续上传</a-button>
  </div>
</template>

<script>
import { ChunkUploader } from '@tievd/cube-chunk-uploader'
  
let loadingHide = null
let splitLoadingHide = null

export default {
  name: 'Demo',

  components: {
    ChunkUploader
  },

  data() {
    return {
      fileList: [],
      uploader: {},
      config: {}, // 基本配置
      bucket: '', // 桶名
      object: '', // 上传对象
      file: {}
    }
  },

  mounted() {
    this.getMinIOConfig()
  },

  methods: {
    async getMinIOConfig() {
      // S3基本配置
      this.config = {
        host: '25.30.9.158',
        port: 9012,
        protocol: 'http:',
        accessKeyId: 'H020ZG975DIWCBNVZ95Q',
        secretAccessKey: 'QYF1jQVtU9zpfZQF+a1LL+I1nKUJRmyy+nJKG5Zs',
        sessionToken:
          'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJIMDIwWkc5NzVESVdDQk5WWjk1USIsImV4cCI6NjA0ODAwMDAwMDAwMDAwLCJwb2xpY3kiOiJjb25zb2xlQWRtaW4iLCJzZXNzaW9uUG9saWN5IjoiZXdvZ0lDQWdJbFpsY25OcGIyNGlPaUFpTWpBeE1pMHhNQzB4TnlJc0NpQWdJQ0FpVTNSaGRHVnRaVzUwSWpvZ1d3b2dJQ0FnSUNBZ0lIc0tJQ0FnSUNBZ0lDQWdJQ0FnSWtWbVptVmpkQ0k2SUNKQmJHeHZkeUlzQ2lBZ0lDQWdJQ0FnSUNBZ0lDSkJZM1JwYjI0aU9pQmJDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWljek02VUhWMFQySnFaV04wSWdvZ0lDQWdJQ0FnSUNBZ0lDQmRMQW9nSUNBZ0lDQWdJQ0FnSUNBaVVtVnpiM1Z5WTJVaU9pQmJDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWlZWEp1T21GM2N6cHpNem82T2lvaUNpQWdJQ0FnSUNBZ0lDQWdJRjBLSUNBZ0lDQWdJQ0I5Q2lBZ0lDQmRDbjA9In0.GY3tRVCrzEQSmdxcfwbRcv0MRTToRHJ_3SK2V5Ov5JK0PHE2zbAUOV17ao20AG-FPB5sK3XJBIpnxGzIb7qSlg',
        region: 'zh-sc-cd'
      }
    },
    async getBucketObject(fileName) {
      this.bucket = 'test'
      this.object = `${fileName}`
    },
    async handleFileChange(file) {
      this.file = file
      await this.getBucketObject(this.file.name)
    },
    async doUpload() {
      this.$refs.chunkUploader.handleUpload()
    },
    handleProgress(data) {
      if (data.status === 'UPLOADING') {
        splitLoadingHide && splitLoadingHide()
        if (loadingHide === null) {
          loadingHide = this.$message.loading('正在上传。。。', 0)
        }
        console.log('ChunkUploader进度:', data.percent)
      } else if (data.status === 'SPLITTING') {
        splitLoadingHide = this.$message.loading('正在分片。。。', 0)
      }
    },
    handleSpeed({ speed, element }) {
      console.log(`speed:${speed}${element}/s`)
    },
    handleSuccess() {
      loadingHide && loadingHide()
      loadingHide = null
      console.log('ChunkUploader上传成功')
    },
    abortUpload() {
      splitLoadingHide && splitLoadingHide()
      loadingHide && loadingHide()
      this.$refs.chunkUploader.abortUpload()
    },
    pauseUpload() {
      this.$refs.chunkUploader.pauseUpload()
    },
    continueUpload() {
      this.$refs.chunkUploader.continueUpload()
    }
  }
}
</script>

示例二 js

<template>
  <div style="margin: 20px;">
    <a-upload name="file" :multiple="false" :fileList="this.fileList" :beforeUpload="this.handleBeforeUpload" :remove="this.handleRemove">
      <a-button> <a-icon type="upload" /> 请选择文件 </a-button>
    </a-upload>
    <br />
    <a-button type="primary" @click="handleUpload">开始上传</a-button>
    <a-button style="margin-left: 10px" type="danger" @click="cubeAbortUpload">终止上传</a-button>
    <a-button style="margin-left: 10px" @click="cubePauseUpload">暂停上传</a-button>
    <a-button style="margin-left: 10px" type="primary" @click="cubeContinueUpload">继续上传</a-button>
  </div>
</template>

<script>
import CubeChunkUploader from '@tievd/cube-chunk-uploader/lib/cubeChunkUploader'
let loadingHide = null
let splitLoadingHide = null

export default {
  name: 'Demo',

  components: {},

  data() {
    return {
      fileList: [],
      uploader: {}
    }
  },

  methods: {
    handleBeforeUpload(file) {
      this.fileList = [file]
      return false
    },
    async handleUpload() {
      const file = this.fileList[0]
      const bucket = 'test'
      const object = file.name
      this.uploader = new CubeChunkUploader(
        {
          host: '25.30.9.158',
          port: 9012,
          protocol: 'http:',
          accessKeyId: 'H020ZG975DIWCBNVZ95Q',
          secretAccessKey: 'QYF1jQVtU9zpfZQF+a1LL+I1nKUJRmyy+nJKG5Zs',
          sessionToken:
            'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJIMDIwWkc5NzVESVdDQk5WWjk1USIsImV4cCI6NjA0ODAwMDAwMDAwMDAwLCJwb2xpY3kiOiJjb25zb2xlQWRtaW4iLCJzZXNzaW9uUG9saWN5IjoiZXdvZ0lDQWdJbFpsY25OcGIyNGlPaUFpTWpBeE1pMHhNQzB4TnlJc0NpQWdJQ0FpVTNSaGRHVnRaVzUwSWpvZ1d3b2dJQ0FnSUNBZ0lIc0tJQ0FnSUNBZ0lDQWdJQ0FnSWtWbVptVmpkQ0k2SUNKQmJHeHZkeUlzQ2lBZ0lDQWdJQ0FnSUNBZ0lDSkJZM1JwYjI0aU9pQmJDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWljek02VUhWMFQySnFaV04wSWdvZ0lDQWdJQ0FnSUNBZ0lDQmRMQW9nSUNBZ0lDQWdJQ0FnSUNBaVVtVnpiM1Z5WTJVaU9pQmJDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWlZWEp1T21GM2N6cHpNem82T2lvaUNpQWdJQ0FnSUNBZ0lDQWdJRjBLSUNBZ0lDQWdJQ0I5Q2lBZ0lDQmRDbjA9In0.GY3tRVCrzEQSmdxcfwbRcv0MRTToRHJ_3SK2V5Ov5JK0PHE2zbAUOV17ao20AG-FPB5sK3XJBIpnxGzIb7qSlg',
          region: 'zh-sc-cd'
        },
        bucket,
        object,
        this.handleComplete,
        this.handleUploadProgress,
        this.handleUploadSpeed
      )
      this.uploader.addFile(file)
      this.uploader.doUpload()
    },
    handleRemove(file) {
      let index = this.fileList.indexOf(file)
      this.fileList.splice(index, 1)
      this.uploader.removeFile(index)
    },
    handleUploadProgress(data) {
      if (loadingHide === null) {
        loadingHide = this.$message.loading('正在上传...', 0)
      }
      console.log('CubeUploader进度:', data.percent)
      if (data.status === 'UPLOADING') {
        splitLoadingHide && splitLoadingHide()
        if (loadingHide === null) {
          loadingHide = this.$message.loading('正在上传...', 0)
        }
        console.log('CubeUploader进度:', data.percent)
      } else if (data.status === 'SPLITTING') {
        splitLoadingHide = this.$message.loading('正在分片...', 0)
      }
    },
    handleUploadSpeed({ speed, element }) {
      console.log(`cube uploader speed:${speed}${element}/s`)
    },
    handleComplete() {
      console.log('上传成功')
      loadingHide && loadingHide()
      loadingHide = null
    },
    cubeAbortUpload() {
      splitLoadingHide && splitLoadingHide()
      loadingHide && loadingHide()
      this.uploader.abortUpload()
    },
    cubePauseUpload() {
      this.uploader.pauseUpload()
    },
    cubeContinueUpload() {
      this.uploader.continueUpload()
    }
  }
}
</script>

示例三 html项目

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>魔方分片上传示例</title>
    <style>
      html {
        font-size: 62.5%;
      }

      #form > .form-item {
        margin-bottom: 20px;
      }

      #file-list {
        margin: 10px 0;
      }

      .file-btn {
        position: relative;
        display: inline-block;
      }

      #file {
        position: absolute;
        left: 0;
        top: 0;
        opacity: 0;
        z-index: 999;
        width: 200px;
      }

      .select-btn {
        width: 200px;
      }
    </style>
    <script type="text/javascript" src="cube-chunk-uploader.min.js"></script>
  </head>

  <body>
    <div id="form">
      <div class="form-item">
        <div class="file-btn">
          <input id="file" type="file" name="file" />
          <button class="select-btn">点击这里选择你要上传的文件</button>
        </div>
      </div>
      <div id="file-list" class="form-list"></div>
      <button id="submit">提交</button>
      <button id="abort">终止</button>
      <button id="pause">暂停</button>
      <button id="continue">继续</button>
    </div>
  </body>
  <script>
    window.onload = () => {
      const fileEle = document.getElementById('file')
      const submitBtn = document.getElementById('submit')
      const abortBtn = document.getElementById('abort')
      const pauseBtn = document.getElementById('pause')
      const continueBtn = document.getElementById('continue')
      const fileList = document.getElementById('file-list')
      let uploader = null
      fileEle.onchange = (e) => {
        const files = e.target.files
        const keys = Object.keys(files)
        keys.forEach((index) => {
          fileList.innerHTML += `<div id="file-${index}" class="file-item" width="100" height="100">${files[index].name}</div>`
        })
      }
      submitBtn.onclick = (e) => {
        function handleComplete() {
          console.log('上传成功')
        }
        function handleUploadProgress({ status, percent }) {
          console.log('进度:', percent)
        }
        function handleUploadSpeed({ speed, element }) {
          console.log(`速度:${speed}${element}/s`)
        }
        
        const file = fileEle.files[0]
        const bucket = 'test'
        const object = file.name
        uploader = new CubeChunkUploader(
          {
            host: '25.30.9.158',
            port: 9012,
            protocol: 'http:',
            accessKeyId: 'H020ZG975DIWCBNVZ95Q',
            secretAccessKey: 'QYF1jQVtU9zpfZQF+a1LL+I1nKUJRmyy+nJKG5Zs',
            sessionToken:
              'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJIMDIwWkc5NzVESVdDQk5WWjk1USIsImV4cCI6NjA0ODAwMDAwMDAwMDAwLCJwb2xpY3kiOiJjb25zb2xlQWRtaW4iLCJzZXNzaW9uUG9saWN5IjoiZXdvZ0lDQWdJbFpsY25OcGIyNGlPaUFpTWpBeE1pMHhNQzB4TnlJc0NpQWdJQ0FpVTNSaGRHVnRaVzUwSWpvZ1d3b2dJQ0FnSUNBZ0lIc0tJQ0FnSUNBZ0lDQWdJQ0FnSWtWbVptVmpkQ0k2SUNKQmJHeHZkeUlzQ2lBZ0lDQWdJQ0FnSUNBZ0lDSkJZM1JwYjI0aU9pQmJDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWljek02VUhWMFQySnFaV04wSWdvZ0lDQWdJQ0FnSUNBZ0lDQmRMQW9nSUNBZ0lDQWdJQ0FnSUNBaVVtVnpiM1Z5WTJVaU9pQmJDaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWlZWEp1T21GM2N6cHpNem82T2lvaUNpQWdJQ0FnSUNBZ0lDQWdJRjBLSUNBZ0lDQWdJQ0I5Q2lBZ0lDQmRDbjA9In0.GY3tRVCrzEQSmdxcfwbRcv0MRTToRHJ_3SK2V5Ov5JK0PHE2zbAUOV17ao20AG-FPB5sK3XJBIpnxGzIb7qSlg',
            region: 'zh-sc-cd'
          },
          bucket,
          object,
          handleComplete,
          handleUploadProgress,
          handleUploadSpeed
        )
        uploader.addFile(file)
        uploader.doUpload()
      }
      abortBtn.onclick = (e) => {
        uploader.abortUpload()
      }
      pauseBtn.onclick = (e) => {
        uploader.pauseUpload()
      }
      continueBtn.onclick = (e) => {
        uploader.continueUpload()
      }
    }
  </script>
</html>

更新日志

CHANGELOG

快速开始

3.0.x

开发技巧

配置文件介绍

皮肤自定义

页面布局

已有页面定制

字典缓存用法

自定义首页

下拉选项滚动错位的解决方法

表单输入默认去掉前后空格

组件库

普通组件

倒计时 CountDown

枚举选择器 CubeSelectEnum

地区联动选择 JAreaLinkage

分类字典选择 JCategorySelect

复选框 JCheckbox

代码编辑器 JCodeEditor

Cron编辑器 JCron

日期选择 JDate

字典选择 JDictSelectTag

字典选择(多选) JMultiSelectTag

字典选择(可搜索) JSearchSelectTag

可编辑表格 JEditableTable

富文本编辑器 JEditor

字符串截取 JEllipsis

文件上传弹窗 JFilePop

表单容器 JFormContainer

图片上传 JImageUpload

导入Modal JImportModal

输入框 JInput

弹窗输入框 JInputPop

Markdown编辑器 JMarkdownEidtor

Modal弹窗 JModal

表格弹窗选择 JPopup

部门选择器 JSelectDepart

部门用户选择器 JSelectUserByDep

用户选择器(多选) JSelectMultiUser

职务选择组件 JSelectPosition

角色选择组件 JSelectRole

高级查询组件 JSuperQuery

分类字典树形下拉选择器 JTreeDict

树形下拉选择组件(异步加载) JTreeSelect

异形树形表格组件 JTreeTable

上传组件 JUpload

JS组件

api/manage.js

mixins/JEditableTableMixin.js

mixins/JeecgListMixin.js

store/modules/app.js

store/modules/user.js

store/mutation-types.js

utils/filter.js

utils/validate.js

utils/hasPermission.js

utils/util.js

utils/vueBus.js

utils/packages/JDictSelectUtil.js

魔方Plugins

上传组件

目录结构

目录结构

Clone this wiki locally