fix: OSS客户端直传
This commit is contained in:
@@ -2,7 +2,10 @@
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { Upload } from 'ant-design-vue';
|
||||
|
||||
// 导入上传相关API和工具函数
|
||||
import { uploadFile } from '#/api/core/upload';
|
||||
import { uploadToOss } from '#/utils/oss-upload';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { Icon } from '#/components/icon';
|
||||
|
||||
defineOptions({
|
||||
@@ -19,12 +22,59 @@ const mValue = useVModel(props, 'value', emits, {
|
||||
defaultValue: props.value,
|
||||
passive: true,
|
||||
});
|
||||
const customRequest = (e: any) => {
|
||||
uploadFile({
|
||||
file: e.file,
|
||||
}).then((data: any) => {
|
||||
/**
|
||||
* 自定义上传请求处理函数
|
||||
*
|
||||
* 该函数根据preferences配置的上传方式,选择使用OSS直传或后端上传:
|
||||
* - 'direct': OSS直传模式,文件直接从浏览器上传到阿里云OSS
|
||||
* - 'backend': 后端上传模式,文件先上传到后端服务器,再由后端上传到OSS
|
||||
*
|
||||
* 上传方式说明:
|
||||
* 1. OSS直传(direct):
|
||||
* - 调用uploadToOss函数,直接上传到OSS
|
||||
* - 减少服务器负载,上传速度更快
|
||||
*
|
||||
* 2. 后端上传(backend):
|
||||
* - 调用uploadFile API,通过后端服务器上传
|
||||
* - 兼容现有功能,所有上传逻辑由后端统一处理
|
||||
*
|
||||
* 兼容性处理:
|
||||
* - 两种上传方式返回的数据结构保持一致:{ url: string }
|
||||
* - 上传成功后,将URL赋值给mValue,触发组件更新
|
||||
*
|
||||
* @param e 上传事件对象,包含file字段(文件对象)
|
||||
*/
|
||||
const customRequest = async (e: any) => {
|
||||
try {
|
||||
// 从preferences中读取上传方式配置
|
||||
// uploadMethod可能的值:'direct'(OSS直传)或 'backend'(后端上传)
|
||||
const uploadMethod = preferences.app.uploadMethod || 'direct';
|
||||
|
||||
let data: { url: string };
|
||||
|
||||
// 根据配置选择上传方式
|
||||
if (uploadMethod === 'direct') {
|
||||
// OSS直传模式:文件直接从浏览器上传到OSS
|
||||
// uploadToOss函数会处理签名获取、文件上传等所有逻辑
|
||||
data = await uploadToOss({
|
||||
file: e.file as File,
|
||||
});
|
||||
} else {
|
||||
// 后端上传模式:文件先上传到后端服务器,再由后端上传到OSS
|
||||
// uploadFile函数会将文件发送到后端API(/upload/image)
|
||||
data = await uploadFile({
|
||||
file: e.file,
|
||||
});
|
||||
}
|
||||
|
||||
// 上传成功,将URL赋值给mValue
|
||||
// mValue是双向绑定的值,更新后会触发父组件的更新
|
||||
mValue.value = data.url;
|
||||
});
|
||||
} catch (error) {
|
||||
// 上传失败,记录错误信息
|
||||
// 注意:这里没有显示错误提示,如果需要可以添加message.error
|
||||
console.error('头像上传失败', error);
|
||||
}
|
||||
};
|
||||
const handleRemove = (e: Event) => {
|
||||
e.stopPropagation();
|
||||
|
||||
@@ -7,7 +7,10 @@ import '@vueup/vue-quill/dist/vue-quill.snow.css';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
// 导入上传相关API和工具函数
|
||||
import { uploadFile } from '#/api/core/upload';
|
||||
import { uploadToOss } from '#/utils/oss-upload';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
@@ -136,33 +139,82 @@ const insertImageToEditor = (quill: any, imageUrl: string): void => {
|
||||
};
|
||||
/**
|
||||
* 图片上传函数
|
||||
*
|
||||
* 该函数根据preferences配置的上传方式,选择使用OSS直传或后端上传:
|
||||
* - 'direct': OSS直传模式,文件直接从浏览器上传到阿里云OSS
|
||||
* - 'backend': 后端上传模式,文件先上传到后端服务器,再由后端上传到OSS
|
||||
*
|
||||
* 上传方式说明:
|
||||
* 1. OSS直传(direct):
|
||||
* - 调用uploadToOss函数,直接上传到OSS
|
||||
* - 减少服务器负载,上传速度更快
|
||||
* - 支持上传进度回调(如果需要可以添加)
|
||||
*
|
||||
* 2. 后端上传(backend):
|
||||
* - 调用uploadFile API,通过后端服务器上传
|
||||
* - 兼容现有功能,所有上传逻辑由后端统一处理
|
||||
*
|
||||
* 兼容性处理:
|
||||
* - 两种上传方式返回的数据结构保持一致:{ url: string }
|
||||
* - 上传成功或失败都会显示相应的提示信息
|
||||
* - 上传完成后,将isUpload标记设置为false,允许下次上传
|
||||
*
|
||||
* @param {File} file - 要上传的图片文件
|
||||
* @returns {Promise<string>} - 返回上传后的图片URL
|
||||
* @returns {Promise<string>} - 返回上传后的图片URL,如果上传失败返回空字符串
|
||||
*/
|
||||
const uploadImage = async (file: File): Promise<string> => {
|
||||
try {
|
||||
// 创建FormData对象,用于发送文件数据
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
// 显示上传中的提示
|
||||
message.loading({ content: '图片上传中...', key: 'imageUpload' });
|
||||
|
||||
return uploadFile({
|
||||
file,
|
||||
}).then((data: any) => {
|
||||
message.success({
|
||||
content: '图片上传成功',
|
||||
key: 'imageUpload',
|
||||
duration: 2,
|
||||
// 从preferences中读取上传方式配置
|
||||
// uploadMethod可能的值:'direct'(OSS直传)或 'backend'(后端上传)
|
||||
const uploadMethod = preferences.app.uploadMethod || 'direct';
|
||||
|
||||
let data: { url: string };
|
||||
|
||||
// 根据配置选择上传方式
|
||||
if (uploadMethod === 'direct') {
|
||||
// OSS直传模式:文件直接从浏览器上传到OSS
|
||||
// uploadToOss函数会处理签名获取、文件上传等所有逻辑
|
||||
data = await uploadToOss({
|
||||
file: file,
|
||||
// 如果需要显示上传进度,可以添加onProgress回调
|
||||
// onProgress: (percent) => {
|
||||
// message.loading({ content: `图片上传中... ${percent}%`, key: 'imageUpload' });
|
||||
// },
|
||||
});
|
||||
isUpload.value = false;
|
||||
return data.url;
|
||||
} else {
|
||||
// 后端上传模式:文件先上传到后端服务器,再由后端上传到OSS
|
||||
// uploadFile函数会将文件发送到后端API(/upload/image)
|
||||
data = await uploadFile({
|
||||
file,
|
||||
});
|
||||
}
|
||||
|
||||
// 上传成功,显示成功提示
|
||||
message.success({
|
||||
content: '图片上传成功',
|
||||
key: 'imageUpload',
|
||||
duration: 2,
|
||||
});
|
||||
|
||||
// 重置上传标记,允许下次上传
|
||||
isUpload.value = false;
|
||||
|
||||
// 返回上传后的图片URL
|
||||
return data.url;
|
||||
} catch (error) {
|
||||
// 处理上传错误
|
||||
console.error('图片上传错误:', error);
|
||||
|
||||
// 显示错误提示
|
||||
message.error({ content: '图片上传失败', key: 'imageUpload', duration: 2 });
|
||||
|
||||
// 重置上传标记,允许重试
|
||||
isUpload.value = false;
|
||||
|
||||
// 返回空字符串,表示上传失败
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,7 +4,10 @@ import { computed, nextTick, onMounted, ref, watch } from 'vue';
|
||||
import { Modal, Upload } from 'ant-design-vue';
|
||||
import type { UploadFile } from 'ant-design-vue';
|
||||
|
||||
// 导入上传相关API和工具函数
|
||||
import { uploadFile } from '#/api/core/upload';
|
||||
import { uploadToOss } from '#/utils/oss-upload';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { Icon } from '#/components/icon';
|
||||
|
||||
defineOptions({
|
||||
@@ -132,11 +135,36 @@ const initSortable = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// 使用原有的uploadFile接口(与upload-image.vue保持一致)
|
||||
/**
|
||||
* 自定义上传请求处理函数
|
||||
*
|
||||
* 该函数根据preferences配置的上传方式,选择使用OSS直传或后端上传:
|
||||
* - 'direct': OSS直传模式,文件直接从浏览器上传到阿里云OSS
|
||||
* - 'backend': 后端上传模式,文件先上传到后端服务器,再由后端上传到OSS
|
||||
*
|
||||
* 两种上传方式的区别:
|
||||
* 1. OSS直传(direct):
|
||||
* - 优点:减少服务器负载,上传速度更快,用户体验更好
|
||||
* - 缺点:需要后端提供签名接口,配置相对复杂
|
||||
* - 实现:调用uploadToOss函数,直接上传到OSS
|
||||
*
|
||||
* 2. 后端上传(backend):
|
||||
* - 优点:兼容现有功能,所有上传逻辑由后端统一处理
|
||||
* - 缺点:增加服务器负载,上传速度相对较慢
|
||||
* - 实现:调用uploadFile API,通过后端服务器上传
|
||||
*
|
||||
* 兼容性处理:
|
||||
* - 两种上传方式返回的数据结构保持一致:{ url: string }
|
||||
* - 确保无论使用哪种方式,组件的行为都是一致的
|
||||
* - 上传成功后,会重新初始化拖拽排序功能
|
||||
* - 如果上传失败,会更新文件状态为error,并调用onError回调
|
||||
*
|
||||
* @param options 上传选项,包含file、onProgress、onSuccess、onError等
|
||||
*/
|
||||
const customRequest = async (options: any) => {
|
||||
const { file, onProgress, onSuccess, onError } = options;
|
||||
|
||||
// 创建上传中的文件项
|
||||
// 创建上传中的文件项,用于在UI中显示上传状态
|
||||
const uploadingFile: FileItem = {
|
||||
uid: file.uid,
|
||||
name: file.name,
|
||||
@@ -144,15 +172,48 @@ const customRequest = async (options: any) => {
|
||||
url: '',
|
||||
};
|
||||
|
||||
// 将上传中的文件添加到文件列表
|
||||
fileList.value = [...fileList.value, uploadingFile];
|
||||
|
||||
try {
|
||||
// 使用原有的uploadFile接口
|
||||
const res = await uploadFile({
|
||||
file: file,
|
||||
});
|
||||
// 从preferences中读取上传方式配置
|
||||
// uploadMethod可能的值:'direct'(OSS直传)或 'backend'(后端上传)
|
||||
const uploadMethod = preferences.app.uploadMethod || 'direct';
|
||||
|
||||
// 更新文件状态为完成
|
||||
let res: { url: string };
|
||||
|
||||
// 根据配置选择上传方式
|
||||
if (uploadMethod === 'direct') {
|
||||
// OSS直传模式:文件直接从浏览器上传到OSS
|
||||
// uploadToOss函数会:
|
||||
// 1. 从后端获取OSS签名信息
|
||||
// 2. 生成全局唯一的文件名(UUID + 时间戳)
|
||||
// 3. 使用FormData构造POST请求直接上传到OSS
|
||||
// 4. 处理上传进度和错误
|
||||
// 5. 返回上传后的文件URL
|
||||
res = await uploadToOss({
|
||||
file: file as File,
|
||||
onProgress: (percent) => {
|
||||
// 将OSS上传进度传递给组件
|
||||
// percent范围:0-100,表示上传百分比
|
||||
if (onProgress) {
|
||||
onProgress(percent);
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// 后端上传模式:文件先上传到后端服务器,再由后端上传到OSS
|
||||
// uploadFile函数会:
|
||||
// 1. 将文件发送到后端API(/upload/image)
|
||||
// 2. 后端接收文件后上传到OSS
|
||||
// 3. 返回上传后的文件URL
|
||||
res = await uploadFile({
|
||||
file: file,
|
||||
});
|
||||
}
|
||||
|
||||
// 上传成功,更新文件状态为完成
|
||||
// 将上传结果中的URL赋值给文件项
|
||||
const updatedFileList = fileList.value.map(item =>
|
||||
item.uid === file.uid
|
||||
? { ...item, status: 'done' as const, url: res.url }
|
||||
@@ -160,17 +221,24 @@ const customRequest = async (options: any) => {
|
||||
);
|
||||
|
||||
fileList.value = updatedFileList;
|
||||
|
||||
// 更新组件的modelValue,触发父组件的更新
|
||||
updateModelValue();
|
||||
|
||||
// 重新初始化排序
|
||||
// 重新初始化拖拽排序功能
|
||||
// 因为文件列表发生了变化,需要重新绑定拖拽事件
|
||||
nextTick(() => {
|
||||
initSortable();
|
||||
});
|
||||
|
||||
// 调用成功回调,通知上传组件上传已完成
|
||||
onSuccess(res);
|
||||
} catch (error) {
|
||||
// 上传失败,记录错误信息
|
||||
console.error('上传失败', error);
|
||||
|
||||
// 更新文件状态为错误
|
||||
// 错误状态的文件会在UI中显示错误图标
|
||||
const updatedFileList = fileList.value.map(item =>
|
||||
item.uid === file.uid
|
||||
? { ...item, status: 'error' as const }
|
||||
@@ -178,6 +246,8 @@ const customRequest = async (options: any) => {
|
||||
);
|
||||
|
||||
fileList.value = updatedFileList;
|
||||
|
||||
// 调用错误回调,通知上传组件上传失败
|
||||
onError(error);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,8 +3,10 @@ import { computed, ref, watch } from 'vue';
|
||||
import { Modal, Upload } from 'ant-design-vue';
|
||||
import type { UploadFile } from 'ant-design-vue';
|
||||
|
||||
// 恢复使用原有的上传接口
|
||||
// 导入上传相关API和工具函数
|
||||
import { uploadFile } from '#/api/core/upload';
|
||||
import { uploadToOss } from '#/utils/oss-upload';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { Icon } from '#/components/icon';
|
||||
|
||||
// 定义接口
|
||||
@@ -68,11 +70,35 @@ const updateModelValue = () => {
|
||||
emit('update:modelValue', urls);
|
||||
};
|
||||
|
||||
// 使用原有的uploadFile接口
|
||||
/**
|
||||
* 自定义上传请求处理函数
|
||||
*
|
||||
* 该函数根据preferences配置的上传方式,选择使用OSS直传或后端上传:
|
||||
* - 'direct': OSS直传模式,文件直接从浏览器上传到阿里云OSS
|
||||
* - 'backend': 后端上传模式,文件先上传到后端服务器,再由后端上传到OSS
|
||||
*
|
||||
* 两种上传方式的区别:
|
||||
* 1. OSS直传(direct):
|
||||
* - 优点:减少服务器负载,上传速度更快,用户体验更好
|
||||
* - 缺点:需要后端提供签名接口,配置相对复杂
|
||||
* - 实现:调用uploadToOss函数,直接上传到OSS
|
||||
*
|
||||
* 2. 后端上传(backend):
|
||||
* - 优点:兼容现有功能,所有上传逻辑由后端统一处理
|
||||
* - 缺点:增加服务器负载,上传速度相对较慢
|
||||
* - 实现:调用uploadFile API,通过后端服务器上传
|
||||
*
|
||||
* 兼容性处理:
|
||||
* - 两种上传方式返回的数据结构保持一致:{ url: string }
|
||||
* - 确保无论使用哪种方式,组件的行为都是一致的
|
||||
* - 如果上传失败,会更新文件状态为error,并调用onError回调
|
||||
*
|
||||
* @param options 上传选项,包含file、onProgress、onSuccess、onError等
|
||||
*/
|
||||
const customRequest = async (options: any) => {
|
||||
const { file, onProgress, onSuccess, onError } = options;
|
||||
|
||||
// 创建上传中的文件项
|
||||
// 创建上传中的文件项,用于在UI中显示上传状态
|
||||
const uploadingFile: FileItem = {
|
||||
uid: file.uid,
|
||||
name: file.name,
|
||||
@@ -80,15 +106,48 @@ const customRequest = async (options: any) => {
|
||||
url: '',
|
||||
};
|
||||
|
||||
// 将上传中的文件添加到文件列表
|
||||
fileList.value = [...fileList.value, uploadingFile];
|
||||
|
||||
try {
|
||||
// 使用原有的uploadFile接口
|
||||
const res = await uploadFile({
|
||||
file: file,
|
||||
});
|
||||
// 从preferences中读取上传方式配置
|
||||
// uploadMethod可能的值:'direct'(OSS直传)或 'backend'(后端上传)
|
||||
const uploadMethod = preferences.app.uploadMethod || 'direct';
|
||||
|
||||
// 更新文件状态为完成
|
||||
let res: { url: string };
|
||||
|
||||
// 根据配置选择上传方式
|
||||
if (uploadMethod === 'direct') {
|
||||
// OSS直传模式:文件直接从浏览器上传到OSS
|
||||
// uploadToOss函数会:
|
||||
// 1. 从后端获取OSS签名信息
|
||||
// 2. 生成全局唯一的文件名(UUID + 时间戳)
|
||||
// 3. 使用FormData构造POST请求直接上传到OSS
|
||||
// 4. 处理上传进度和错误
|
||||
// 5. 返回上传后的文件URL
|
||||
res = await uploadToOss({
|
||||
file: file as File,
|
||||
onProgress: (percent) => {
|
||||
// 将OSS上传进度传递给组件
|
||||
// percent范围:0-100,表示上传百分比
|
||||
if (onProgress) {
|
||||
onProgress(percent);
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// 后端上传模式:文件先上传到后端服务器,再由后端上传到OSS
|
||||
// uploadFile函数会:
|
||||
// 1. 将文件发送到后端API(/upload/image)
|
||||
// 2. 后端接收文件后上传到OSS
|
||||
// 3. 返回上传后的文件URL
|
||||
res = await uploadFile({
|
||||
file: file,
|
||||
});
|
||||
}
|
||||
|
||||
// 上传成功,更新文件状态为完成
|
||||
// 将上传结果中的URL赋值给文件项
|
||||
const updatedFileList = fileList.value.map(item =>
|
||||
item.uid === file.uid
|
||||
? { ...item, status: 'done' as const, url: res.url }
|
||||
@@ -96,11 +155,18 @@ const customRequest = async (options: any) => {
|
||||
);
|
||||
|
||||
fileList.value = updatedFileList;
|
||||
|
||||
// 更新组件的modelValue,触发父组件的更新
|
||||
updateModelValue();
|
||||
|
||||
// 调用成功回调,通知上传组件上传已完成
|
||||
onSuccess(res);
|
||||
} catch (error) {
|
||||
// 上传失败,记录错误信息
|
||||
console.error('上传失败', error);
|
||||
|
||||
// 更新文件状态为错误
|
||||
// 错误状态的文件会在UI中显示错误图标
|
||||
const updatedFileList = fileList.value.map(item =>
|
||||
item.uid === file.uid
|
||||
? { ...item, status: 'error' as const }
|
||||
@@ -108,6 +174,8 @@ const customRequest = async (options: any) => {
|
||||
);
|
||||
|
||||
fileList.value = updatedFileList;
|
||||
|
||||
// 调用错误回调,通知上传组件上传失败
|
||||
onError(error);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user