vue3上传文件组件方法封装

1.在utils文件夹下新建upload.js文件

javascript 复制代码
import { ElMessage } from 'element-plus'
import axios from 'axios';
// 参数fn是请求后端的接口;file是上传文件的数据,上传组件自带的参数;data是fn接口传递的数据;fileType是文件类型;size是文件大小
export async function upload (fn, file, data, fileType, size) {
  // 附件格式
  if (fileType) {
    const fileCut = file.file.name.substring(file.file.name.lastIndexOf('.') + 1)
    if (fileType.indexOf(fileCut.toLowerCase()) === -1) { // 处理后缀名大小写问题
      ElMessage.warning(`上传的附件格式只能是 ${fileType.toString()}!`);
      return Promise.reject(false)
    }
  }
  // 附件 大小   
  if (size) {
    const isLt2M = file.file.size / 1024 / 1024 < size
    if (!isLt2M) {
      return ElMessage.warning(`上传的附件大小不能超过 ${size}MB!`)
    }
  }
  let type = getContentType(file.file.name)
  let arr = {}
  // 使用同步方法返回参数 否则获取返回值时接口还没执行完成   
  await fn(data).then(res => {
    axios.put(res.data.uploadUrl,file.file,{
      headers: {
        'Content-Type': type
      }
    })
    
   arr = res.data
  })
  return Promise.resolve(arr)
}

function getContentType(filename) {
  let fileSuffix = filename.substring(filename.lastIndexOf(".") + 1);
  let contentType = 'multipart/form-data'
  switch(fileSuffix){
    case 'png':
      contentType = 'image/png';
      break
    case 'jpg':
      contentType = 'image/jpeg';
      break
    case 'jpeg':
      contentType = 'image/jpeg';
      break
    case 'gif':
      contentType = 'image/gif';
      break
    case 'pdf':
      contentType = 'application/pdf';
      break
    case 'doc':
      contentType = 'application/msword';
      break
    case 'docx':
      contentType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
      break
    case 'xls':
      contentType = 'application/vnd.ms-excel';
      break
    case 'xlsx':
      contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
      break
  }
  return contentType
}

说明:参数fn是请求后端的接口;file是上传文件的数据,上传组件自带的参数;data是fn接口传递的数据;

2.页面中使用

html 复制代码
<el-upload action="#" list-type="picture-card" :http-request="headImgUpload" :show-file-list="false">
              <div style="width: 100%;height: 100%;">
                <div v-if="!accountInfBaseVO.avatar" style="position: relative;top: 50%;transform: translateY(-50%);">
                  <svg-icon icon-class="jia" style="height: 100px;width: 100px;" />
                </div>
                <div v-else style="position: relative;top: 50%;transform: translateY(-50%);">
                  <svg-icon icon-class="jia" style="height: 100px;width: 100px;" />
                </div>
              </div>
            </el-upload>
javascript 复制代码
import { upload } from '@/utils/upload' // 封装的方法
import { getUpload,accountInfoUpdate} from "@/api/accountinfo";//上传头像接口和修改头像接口

// 修改头像
function headImgUpload(file) {
  const fileType = ['jpg', 'png', 'jpeg']
  if (file.file.name.length > 200) {
    return ElMessage.error("文件名不能超过200字符")
  }
  const data = upload(getUpload, file, { fileName: file.file.name, type: 2 }, fileType, 2)
  data.then(res => {
    if (!res.successUrl) {
      return
    }
    accountInfBaseVO.value.avatar = res.successUrl;
    let data = {
      nickName: accountInfBaseVO.value.nickName,
      avatar: accountInfBaseVO.value.avatar,
      industry: personalAuthenticationVO.value?.industry
    }
    accountInfoUpdate(data).then(res => {
      isImgEdit.value = false;
      ElMessage.success("修改成功!")
      getAccountInfo();
      RealNameRef.value.getAccountInfo();
    })
  })
}

说明:整个使用过程中的重点在于标签上属性http-request的使用;方法中重点在于封装方法的调用getUpload(),该封装方法的第一个参数是将文件上传到后端存储的接口,这一步只是上传到了后端数据库,要渲染在页面上就需要请求后端的另一个接口(修改头像接口)。

相关推荐
汪汪大队u15 分钟前
为什么 filter-policy 仅对 ASBR 的出方向生效,且即使在该生效场景下,被过滤的路由在协议内部(如协议数据库)依然存在,没有被彻底移除?
服务器·前端·网络
慧一居士21 分钟前
vue.config.js 文件功能介绍,使用说明,对应完整示例演示
前端·vue.js
颜酱24 分钟前
用导游的例子来理解 Visitor 模式,实现AST 转换
前端·javascript·算法
木易 士心33 分钟前
Nginx 基本使用和高级用法详解
运维·javascript·nginx
蒙特卡洛的随机游走42 分钟前
Spark的宽依赖与窄依赖
大数据·前端·spark
共享家95271 小时前
QT-常用控件(多元素控件)
开发语言·前端·qt
幸运小圣1 小时前
Iterator迭代器 【ES6】
开发语言·javascript·es6
葱头的故事1 小时前
将传给后端的数据转换为以formData的类型传递
开发语言·前端·javascript
中微子1 小时前
🚀 2025前端面试必考:手把手教你搞定自定义右键菜单,告别复制失败的尴尬
javascript·面试
_23331 小时前
vue3二次封装element-plus表格,slot透传,动态slot。
前端·vue.js