Ant-design-vue 实现大文件分片上传

      <div id="fileUpload">
            <a-form-item :labelCol="labelCol"
                         :wrapperCol="wrapperCol"
                         label="文件"
                         extra="最多5个;附件格式:pdf、word、excel、ppt、png、jpg、jpeg、 
                                png、zip、rar文件大小不超过512MB;"
                         has-feedback>
              <a-upload
                v-decorator="['attachData',
          {
            valuePropName: 'fileList',
            getValueFromEvent: normFile,
             rules: [{ required: true, message: '请选择文件上传!'}]
          }
        ]"
                name="file"
                list-type="picture"
                accept=".pdf,.doc,.docx,image/jpeg,image/jpg,image/png,.xlsx,.xls,.ppt,.zip,.rar"
                :beforeUpload="beforeUpload"
                :remove="remove"
                :data="uploadData"
                @change="handleChange"
                :customRequest="customRequest"
              >
                <a-button>
                  <a-icon type="upload"/>
                  上传申报文件
                </a-button>
              </a-upload>
            </a-form-item>
       </div>

跟上期一样只是这次的上传使用自定义的 

customRequest  :通过覆盖默认的上传行为,可以自定义自己的上传实现
    // 自定义文件上传
    customRequest (option) {
      partUpload({
        file: option.file,
        onProgress: (num) => {
          option.onProgress({ percent: num })
        }
      }).then(res => {
              this.$message.success(`上传成功`)

        }
      }).catch(err => {
       
      })
    }

下面分片的方法customRequest 的方法就下的js

import _ from 'lodash'
import api from '@/api'
import {originApi} from '../api/base'
import Big from 'big.js'
import FileMd5 from './fileMd5.js'
import {Modal} from 'ant-design-vue'
// 分片上传接口
const actionUrl = 'xxxxx'//上传使用的地址

// 分片上传暂存参数
const partData = {}

// 分片上传默认参数
const defaultOption = {
  downloadFlag: 1,
  publicFlag: false,
  totalSize: 0,
  currentSize: 1024 * 1024 * 20, // 20M
  appendFlag: true,
  position: 0,
  times: 1,
  fileName: '',
  objectKey: '',
  chunks: [],
  onProgress: (e) => {},
  cancelToken: (e) => {}
}

// 获取分片上传的接口参数
const getPartFile = (tid) => {
  const data = partData[tid]
  const formData = new FormData()
  const chunk = data.chunks[data.times - 1]
  const blob = new Blob([chunk.currentBuffer], { type: 'application/octet-stream' })
  formData.append('file', blob, chunk.chunkMD5)
  formData.append('position', chunk.position)
  formData.append('times', data.times)
  formData.append('downloadFlag', data.downloadFlag)
  formData.append('publicFlag', data.publicFlag)
  formData.append('totalSize', data.totalSize)
  formData.append('fileName', data.fileName)
  formData.append('currentSize', data.currentSize)
  formData.append('appendFlag', data.appendFlag)
  if (data.uploadId) formData.append('uploadId', data.uploadId)
  if (data.objectKey) formData.append('objectKey', data.objectKey)
  return formData
}

// 上传分片文件
const uploadPart = (tid, resolve, reject) => {
  const formData = getPartFile(tid)
  const data = partData[tid]
  originApi.post(
    actionUrl,
    formData,
    {
      onUploadProgress: (progressEvent) => {
        const uploadProgress = new Big(progressEvent.loaded).div(progressEvent.total).div(data.chunks.length)
        const totalComplete = new Big(data.times - 1).div(data.chunks.length).plus(uploadProgress)
        const percent = new Big(totalComplete).times(100)
        data.percent = parseFloat(percent)
        data.onProgress(data.percent)
      },
      cancelToken: new api.CancelToken(function executor (c) {
        data.cancelToken(c)
      })
    }
  ).then(res => {
    if (res.data.code === -702) {
      resolve(res || {})
      Modal.error(
        {
          okText: '确定',
          title: '提示',
          mask: false,
          content: res.data.message
        }
      )
    } else if (res.data.errors && res.data.errors.length > 0) { // 接口报错时
      const { title } = res.data.errors[0]
      reject(new Error(title))
    } else { // 接口正常时
      const resData = res.data.data || {}
      if (!data.objectKey) data.objectKey = resData.objectKey
      if (!data.uploadId) data.uploadId = resData.uploadId
      data.times++
      if (data.percent >= 100) {
        resolve(resData)
        // 上传成功后清除已有数据,释放内存
        delete partData[tid]
      } else {
        uploadPart(tid, resolve, reject)
      }
    }
  }).catch(err => {
    reject(err)
    
  })
}


export default (opt) => {
  const timeStampId = new Date().getTime().toString()
  partData[timeStampId] = _.extend({}, defaultOption, opt)
  return new Promise((resolve, reject) => {
    const data = partData[timeStampId]
    const file = data.file
    FileMd5(file, (e, md5, chunks) => {
      if (e) {
        reject(new Error(e))
      } else {
        data.fileName = file.name
        data.totalSize = file.size
        data.times = 1
        data.chunks = chunks
        uploadPart(timeStampId, resolve, reject)
      }
    })
  })
}

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Vue3.0中使用ant-design-vue文件,需要先安装ant-design-vue和axios模块: ```bash npm install ant-design-vue axios --save ``` 然后在需要使用上组件的页面中,引入ant-design-vue和axios模块: ```javascript import { Upload, Button } from 'ant-design-vue'; import axios from 'axios'; ``` 然后在页面中,添加上组件: ```html <template> <div> <upload :action="uploadUrl" :headers="headers" :showUploadList="false" :beforeUpload="beforeUpload" :onSuccess="onSuccess" :onError="onError" > <button> <a-button> <a-icon type="upload" /> Click to Upload </a-button> </button> </upload> </div> </template> ``` 其中,`uploadUrl`是上文件的接口地址,`headers`是上文件时需要携带的请求头,`beforeUpload`是上文件前的校验函数,`onSuccess`和`onError`分别是上成功和上失败的回调函数。 在页面的`script`中,需要定义这些属性的值以及`beforeUpload`、`onSuccess`、`onError`函数的实现: ```javascript export default { name: 'UploadPage', components: { Upload, Button }, data() { return { uploadUrl: '/api/upload', headers: { Authorization: 'Bearer ' + localStorage.getItem('token') } }; }, methods: { beforeUpload(file) { const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'; if (!isJpgOrPng) { this.$message.error('You can only upload JPG/PNG file!'); return false; } const isLt2M = file.size / 1024 / 1024 < 2; if (!isLt2M) { this.$message.error('Image must smaller than 2MB!'); return false; } return true; }, onSuccess(response, file) { this.$message.success('Upload successfully!'); }, onError(error, response, file) { this.$message.error('Upload error!'); } } }; ``` 其中,`beforeUpload`函数用来进行文件类型和大小的校验,`onSuccess`和`onError`函数用来处理上成功和上失败的情况。 最后,在页面的`style`中,可以添加一些样式来美化上按钮: ```css button { margin-top: 16px; } button .ant-btn { width: 100%; } button .anticon-upload { margin-right: 8px; } ``` 这样,就可以在Vue3.0中使用ant-design-vue文件了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值