前段时间刚好做到这个需求在这里记录一下希望能帮助到大家!
首先可以先看看七牛云的开发者中心:七牛云开发中心
我这里是使用vue3.x+ts框架开发的

按照文档所说我们需要先安装一下七牛云的SDK

npm install qiniu-js

然后在页面上引入:

const qiniu = require('qiniu-js')
// or
import * as qiniu from 'qiniu-js'

使用的是antd的上传组件:(我给封装起来了:UploadDragger)

<a-drawer width="60%" title="上传文件"  v-model:visible="ShowUpload">
    <UploadDragger :key="uploadTimers" @onchangUpload="onChangUploadDragger" />
     <div class="drawer_footer">
       <a-button :disabled="pageLoading" type="primary" @click="ConfiromUpload">确定</a-button>
       <a-button :disabled="pageLoading" @click="ShowUpload = false">取消</a-button>
     </div>
</a-drawer>

UploadDragger组件:

<template>
  <div class="UploadDragger">
    <a-upload-dragger
      v-model:fileList="fileList"
      name="file"
      :multiple="true"
      :before-upload="() => {return false}"  <!--加上这个上传不写action才不会报错并且能拿到file -->
      @change="handleChange"
    >
      <p class="ant-upload-drag-icon">
        <img src="@/assets/images/afferent.png" alt="传入" srcset="" />
      </p>
      <p class="ant-upload-text">将文件拖至此处,或点击上传</p>
      <p class="ant-upload-hint">
        仅支持 word/ecxcel/ppt /jpg png/mp4/mp3/rar/zip 格式
      </p>
    </a-upload-dragger>
  </div>
</template>

<script lang="ts">
import { defineComponent, getCurrentInstance, ref } from 'vue';
interface FileItem {
  lastModified: string|undefined;
  uid: string;
  name?: string;
  status?: string;
  response?: string;
  url?: string;
}

interface FileInfo {
  file: FileItem;
  fileList: FileItem[];
}
export default defineComponent({
  emits:['onchangUpload'],
   setup(props, { emit }) {
    //获取当前组件实例对象(类似this)
    const { proxy }: any = getCurrentInstance();
    const fileList = ref([]);
    /**
     * 上传触发获取上传文件数据事件
     * @info 上传的文件数据
     * */ 
    const handleChange = (info: FileInfo) => {
      // console.log(info)
      
      let find = false; // 校验字段
      for (let i = 0; i < info.fileList.length; i++) { // 校验数组对象中的lastModified是否存在重复数据
        let item = info.fileList[i]
        for (let j = i + 1; j < info.fileList.length; j++) {
          let ele = info.fileList[j]
          if (item.lastModified == ele.lastModified) { find = true; break;}
        }
        if (find) break;
      }
      // console.log(find) 
      if(find){ // 返回true存在重复数据,false不存在重复数据
        proxy.$message.error('请勿重复上传相同文件!!!')
      }
      
      // 去重数组中相同的对象数据
      let remObj = {};
      info.fileList = info.fileList.reduce((cur:any,next:any) => {remObj[next.lastModified] ? "" : remObj[next.lastModified] = true && cur.push(next);
      return cur;
      },[]); //设置cur默认类型为数组,并且初始值为空的数组

      remObj = {};
      fileList.value = info.fileList.reduce((cur:any,next:any) => {remObj[next.lastModified] ? "" : remObj[next.lastModified] = true && cur.push(next);
      return cur;
      },[]); //设置cur默认类型为数组,并且初始值为空的数组

      emit('onchangUpload', info)
    };
    return {
      handleChange,
      fileList,
    };
  },
})
</script>

回到主页面开始调事件:
computeMD5()方法的使用查看:文件上传md5计算

setup(){
	const state = reactive<any>({
		// 上传参数
	      ShowUpload:false,
	      FileObj:[], // 存储上传的文件
	      uploadTimers: new Date().getTime(),// 刷新避免存在缓存
	})
	/**
	  * 上传获取文件事件
	  * @res 上传的文件数据
	 * */ 
    const onChangUploadDragger = (res:any) =>{
      // console.log('父组件调用打印:')
      state.FileObj = computeMD5(res.fileList)
      // console.log(state.FileObj)
    };
	
	/**
    * 确认上传事件
    * @param ShowUpload 隐藏上传弹窗
    * */ 
    const ConfiromUpload = ()=>{
      if(state.FileObj.namelist.length == 0){
        proxy.$message.error('请先上传文件再进行确认!')
        return
      }
      state.ShowUpload = false // 关闭弹窗
      state.FileObj.namelist.forEach((item:any, index: any)=>{
        let size = state.FileObj.fileSizelist[index]
        let md5 = state.FileObj.md5list[index]
        let params = {
          fileName: item,
          fileSize: size,
          fileMd5: md5
        }
        let file = state.FileObj.Filelist[index] // 获取文件流
        SaveCommitUpload(params, file) // 写入提交文件上传请求事件;
      })
    };

    /**
     * 写入提交文件上传请求事件
     *@params 请求参数
     *@file 文件流数据
     * */ 
    const SaveCommitUpload = (params: any, file: any) =>{
      $http.getCommitUpload(params).then((res) => {  // 请求后端返回的七牛云token和其他参数
        	UploadFilesQiniuCloud(file, res.config); //上传文件到七牛云事件
        }
        
      }).catch((err) => {})
    };

    /**
     * 上传文件到七牛云事件
     *@file 文件流数据
     *@res 回调返回的文件上传数据
     *@Callback 请求成功后请求的文件上传结果事件
     * */ 
    const UploadFilesQiniuCloud = (file:any, res:any) =>{
      // console.log(file)
      // console.log(res)
      // return
      const key = res.key // 上传文件名
      const token = res.tempToken // 七牛云token
      const observer = {
        next: (response: any) => {
          console.log('上传进度'+Math.floor(response.total.percent)+'%')
          // console.log(response)
        },
        error: (err: any) => {
          // 失败
          proxy.$message.error('上传失败:' + err.message)
          console.log(err)
        },
        complete: (response:any) => {
          // 成功回调
          console.log(response)
        }
      }
      const putExtra: Object = {
        fname: file.name,   //上传文件名称
        params: {},
        mimeType: file.type,  // 文件类型
        // mimeType: ['image/png', 'image/jpeg', 'image/gif']
      }
      const config = {
        useCdnDomain: true,
        region: qiniu.region.z2, // 所在地域 这个可以问问后端域名所属区域(我这个是华南)
        chunkSize: res.config.chunkSize // 这个是切片大小,一般默认是4
      }
      const observable = qiniu.upload(file, key, token, putExtra, config)
      observable.subscribe(observer) // 上传开始
    };

	return {
	...toRefs(state),
	onChangUploadDragger,
	ConfiromUpload,
	}
}

至此七牛云的上传就完成了,需要注意的七牛云的token是从后端获取的,前端拿着token才能去访问七牛云并将文件上传上去;
代码写的比较冗余,请多多见谅。主要是为自己记录的哈

Logo

前往低代码交流专区

更多推荐