当前位置: 首页 > news >正文

vue3+antd实现华为云OBS文件拖拽上传详解

1、文件上传核心流程

  1. 选择文件​​:用户通过拖拽或点击选择文件
  2. 手动触发上传​​:点击"确定"按钮后开始上传(阻止自动上传)
  3. ​获取上传凭证​​:从后端获取华为云OBS的上传配置
  4. 构建表单数据​​:按照华为云要求组织表单数据
  5. 执行上传​​:发送POST请求到华为云OBS
  6. 返回结果​​:处理上传结果并返回文件信息

2、关键参数说明

参数说明来源
file要上传的文件对象用户选择
businessName业务分类名称组件props传入
privateMode是否私有模式默认为true
sourceType数据源类型('ka'/'oin')组件props传入
bucketOBS桶名称后端接口返回
endpointOBS服务端点后端接口返回
policy上传策略后端接口返回
signature签名后端接口返回
accessId访问密钥ID后端接口返回

3、部分字段解释

1、业务名称 (businessName)​

​作用​​:

  • ​文件分类存储​​:用于在华为云OBS中创建业务专属目录,实现文件按业务线分类存储
  • ​权限隔离​​:不同业务文件可以设置不同的访问权限
  • 检索过滤​​:便于后续按业务维度查询和管理文件
// 上传到路径:kafile/订单业务/2023/08/30/时间戳.jpg
pathParts = ['kafile', '订单业务', '2023/08/30', '1693388800000.jpg']// 如果没有业务名称则上传到:kafile/2023/08/30/时间戳.jpg
pathParts = ['kafile', '2023/08/30', '1693388800000.jpg']

​2、数据源类型 (sourceType)​

​作用​​:

  • 多账户切换​​:对接不同华为云账号或服务端点
  • 差异化处理​​:不同来源的文件可能需要不同的上传策略
  • 扩展性​​:预留的枚举字段方便后续接入新存储系统

3、为什么需要这些参数?​

1.主要用来区分调不同服务的接口来获取华为云OBS的上传凭证​​​

  • 同一系统可能服务多个业务线(如大客户、oin等)
  • 不同业务对文件存储的要求不同(如订单需要长期保存,临时文件只需保留7天)

2.为什么需要调用后端接口获取华为云OBS的上传凭证?

华为云OBS的直传需要以下安全凭证:(接口返回)

{bucket: "your-bucket-name",       // 存储桶名称endpoint: "obs.cn-south-1.myhuaweicloud.com", // 区域端点policy: "eyJleHBpcmF0aW9uIjo...", // 经过Base64编码的上传策略signature: "Dq1YpZxlQODhQwM...",   // 对policy的签名accessId: "AKIDEXAMPLE"           // 临时访问密钥ID
}

安全原因​​:直接在前端存储华为云AK/SK是极度危险的,必须通过后端中转。

3.为什么还需要拼接上传url?

在华为云OBS(对象存储服务)中,拼接上传URL (https://${bucket}.${endpoint}) 是​​华为云OBS API的强制要求​​,这种设计涉及到底层的访问机制和安全策略。

华为云OBS的访问URL遵循特定格式:

https://[bucket名称].[区域端点]

4.为什么需要获取当前日期格式的目录?

getCurrentDateDir() 是一个用于 ​​按日期自动生成文件存储目录​​ 的工具函数。

自动组织文件存储结构​

将文件按日期分目录存储,最终路径如:
kafile/业务名/2023/8/30/文件名.ext

4、代码实现

<template><a-upload-dragger:max-count="maxCount"//最大上传文件数:before-upload="beforeUpload"//上传前的处理函数v-model:fileList="fileList"//双向绑定文件列表数据 ><p>点击或拖拽文件上传</p></a-upload-dragger><a-button type="link" @click="handleOk">确定</a-button>
</template><script setup>
import { ref } from 'vue';
import { message } from 'ant-design-vue';
import dayjs from 'dayjs';const props = defineProps({maxCount: Number,// 最大上传文件数量businessName: String,// 业务名称sourceType: { type: String, default: 'ka' }// 数据源类型,默认'ka'
});const emits = defineEmits(['handleUpload']);const fileList = ref([]);// 阻止自动上传的函数,返回false表示阻止默认上传行为
const beforeUpload = () => false;// 处理确定按钮点击
const handleOk = async () => {if (!fileList.value.length) {// 检查是否有文件被选中message.warning('请先选择文件');return;}try {// 获取第一个文件的原始文件对象const file = fileList.value[0].originFileObj;// 调用上传函数并等待结果const result = await uploadToHuaweiOBS({file,// 文件对象businessName: props.businessName,// 业务名称sourceType: props.sourceType// 数据源类型});emits('handleUpload', {bucketName: result.bucketName,// 存储桶名称oriFileName: result.originalName,// 原始文件名fileName: result.fileNameWithoutDir,// 不含目录的文件名file,// 文件对象dir: 'kafile'// 存储目录});message.success('文件上传成功');} catch (error) {message.error(`上传失败: ${error.message}`);}
};// 华为云OBS上传函数
const uploadToHuaweiOBS = async ({ file, businessName = '', sourceType = 'ka' }) => {// 1. 调用后端接口获取华为云OBS的上传凭证const authData = await getUploadAuth(sourceType);// 2. 准备上传参数const { bucket, endpoint, policy, signature, accessId } = authData;// 构建上传URLconst url = `https://${bucket}.${endpoint}`;// 3. 构建文件路径const fileDir = getCurrentDateDir(); // 获取当前日期格式的目录const fileName = generateFileName(file.name); // 生成新文件名const folder = 'kafile'; // 设置存储目录// 构建完整路径数组const pathParts = [folder, fileDir, fileName];// 如果有业务名称,插入到路径中if (businessName) pathParts.splice(1, 0, businessName);// 拼接完整文件路径const fileKey = pathParts.join('/');// 4. 构建表单数据用来做文件上传const formData = new FormData();// 按照华为云要求的顺序添加字段formData.append('key', fileKey);// 文件路径formData.append('policy', policy);// 上传策略formData.append('AccessKeyId', accessId);// 访问密钥IDformData.append('signature', signature);// 签名formData.append('file', file);// 文件本身// 5. 执行上传(这里是直传华为云OBS,注意不是后端接口)await axios.post(url, formData);// 6. 返回结果(这里是华为云OBS返回的参数)return {fileUrl: `${url}/${fileKey}`,// 完整文件URLfileName,// 生成的文件名bucketName: bucket,// 存储桶名称originalName: file.name,// 原始文件名fileNameWithoutDir: pathParts.slice(1).join('/'),// 不含根目录的路径relativePath: fileKey,// 相对路径businessName// 业务名称};
};// 辅助函数
// 如需补零格式(推荐):使用 'YYYY/MM/DD'
const getCurrentDateDir= () => {return dayjs().format('YYYY/MM/DD'); // 输出示例: "2023/08/30"
};// 生成带时间戳的新文件名
const generateFileName = (originalName) => {const ext = originalName.split('.').pop();// 获取文件扩展名return `${Date.now()}.${ext}`;// 时间戳+扩展名
};
</script>

5、组件使用

<template><HuaweiUpload:max-count="3"business-name="customer-service"source-type="oin"@handle-upload="handleUpload"/>
</template><script setup>
import { ref } from 'vue';
import { message } from 'ant-design-vue';const uploading = ref(false);const handleUpload = async (fileInfo) => {uploading.value = true;const formData = new FormData()//创建表单数据对象for (const key in data) {//遍历数据对象并添加到表单formData.append(key, data[key])}try {//调用自己的业务逻辑const { data } = await weeklyImport(formData)if (data.importStatus === '1') {useMessage().success('导入成功')} else if (data.importStatus === '2') {useMessage().error('导入失败,请查看历史记录')}} catch (error) {useMessage().warning('导入失败,请查看历史记录')} finally {//隐藏加载状态uploading.value = false}
};
</script>

http://www.dtcms.com/a/356263.html

相关文章:

  • 华为云CCE的Request和Limit
  • AI+云,双擎驱动——华为云让智能触手可及
  • Django Admin 管理工具
  • Java中协变逆变的实现与Kotlin中的区别
  • 如何用 Kotlin 在 Android 手机开发一个应用程序获取国家或地区信息
  • echo、seq、{}、date、bc命令
  • 如何用 Kotlin 在 Android 手机开发一个应用程序获取网络时间
  • OpenCV之霍夫变换
  • 在C++11中实现函数式编程的组合子
  • AI推介-大语言模型LLMs论文速览(arXiv方向):2025.04.25-2025.04.30
  • React Native 初体验
  • rabbitmq学习笔记 ----- 多级消息延迟始终为 20s 问题排查
  • OpenCV 图像预处理核心技术:阈值处理与滤波去噪
  • LubanCat-RK3568 UART串口通信,以及遇到bug笔记
  • CRYPT32!CryptMsgUpdate函数分析和asn.1 editor nt5inf.cat 的总览信息
  • 第八篇 永磁同步电机控制-MTPA、MTPV
  • 深入解析Qt节点编辑器框架:数据流转与扩展机制(三)
  • 实时音视频延迟优化指南:从原理到实践
  • 零知开源——基于STM32F407VET6和ADXL345三轴加速度计的精准运动姿态检测系统
  • Blender模拟结构光3D Scanner(三)获取相机观测点云的真值
  • OpenCV 基础知识总结
  • 无懈可击的 TCP AIMD
  • 亚马逊季节性产品运营策略:从传统到智能化的演进
  • kimi浏览器助手-月之暗面推出的智能浏览器扩展
  • docker中的mysql有中文显示问题跟大小写区分问题?
  • Python从入门到高手9.4节-基于字典树的敏感词识别算法
  • 使用Python脚本执行Git命令
  • React 状态丢失:组件 key 用错引发的渲染异常
  • Rust 安装与运行指南
  • Custom SRP - LOD and Reflections