Appearance
图片上传组件
本文档引用文件
目录
简介
UploadImage 组件是一个用于实现图片上传功能的前端组件,支持多图上传、压缩、预览、排序和删除。该组件与后端OSS服务深度集成,使用S3兼容的存储协议进行文件直传,并通过预签名URL机制保障上传安全。上传后的文件可通过ID生成访问链接,并支持缩略图、格式转换和CDN加速。
组件结构与流程
图示来源
核心上传流程
1. 用户选择文件
用户通过点击“+”按钮触发隐藏的 <input type="file">,选择图片文件。
2. 前端验证
组件在上传前进行多项验证:
- 文件大小限制(
maxFileSize) - 文件类型限制(
accept属性) - 最大上传数量(
maxSize)
若验证失败,使用 ElMessage.error 提示用户。
3. 图像压缩处理
调用 checkImageMaxSize 函数对图像进行压缩:
- 自动压缩为 WebP 格式
- 限制最大宽度和高度(默认 1920x1080)
- 使用
@jsquash/webp和@jsquash/resize进行无损压缩
4. 调用上传接口
通过 uploadFile 方法将文件上传至后端,返回唯一文件ID。
5. 更新模型值
将返回的文件ID(或多个ID用逗号分隔)通过 emit("update:modelValue") 同步到父组件。
本节来源
安全与验证机制
文件类型验证
通过 accept 属性限制可上传的MIME类型:
ts
accept: "image/webp,image/png,image/jpeg,image/svg+xml"大小限制
- 单文件大小限制:
maxFileSize(默认 50MB) - 图像尺寸限制:
maxImageWidth和maxImageHeight - 最多上传数量:
maxSize(默认 1 张)
安全元数据
上传时,后端自动添加以下元数据:
x-amz-meta-filename:原始文件名x-amz-meta-is_public:是否公开访问x-amz-meta-tenant_id:租户ID(用于多租户隔离)x-amz-meta-db:数据库标识
本节来源
后端OSS服务集成
1. 上传接口
后端提供 /upload 接口,接收 multipart/form-data 格式文件。
2. S3 存储集成
使用 s3 Rust 库与兼容S3协议的对象存储服务通信:
- 配置
oss_endpoint、oss_accesskey、oss_secretkey - 使用
Bucket::new创建存储桶实例 - 支持路径风格访问(
with_path_style())
3. 文件ID生成
若未指定ID,则调用 get_short_uuid() 生成短UUID作为文件唯一标识。
4. 元数据写入
上传时自动写入文件名、租户ID、数据库标识等元数据,用于权限控制和溯源。
图示来源
回调与业务数据关联
上传成功后,组件通过 emit("update:modelValue", id) 将文件ID返回给父组件。父组件可将该ID关联到业务模型,例如:
ts
// 用户头像上传
user.avatarId = uploadedId;
// 商品图片管理
product.imageIds = [id1, id2, id3];通过 getDownloadUrl({ id }) 或 getImgUrl({ id }) 可生成访问URL,支持:
- 直接下载
- 缩略图生成(支持宽高、格式、质量参数)
- CDN加速(通过反向代理)
最佳实践示例
用户头像上传
vue
<UploadImage
v-model="user.avatarId"
:maxSize="1"
:maxFileSize="1024 * 1024 * 2"
accept="image/jpeg,image/png"
:compress="true"
:maxImageWidth="400"
:maxImageHeight="400"
/>商品图片管理
vue
<UploadImage
v-model="product.imageIds"
:maxSize="5"
:maxFileSize="1024 * 1024 * 5"
accept="image/*"
:compress="true"
itemHeight="120"
/>本节来源
性能调优建议
1. 图像压缩
启用 compress 选项,自动将图片压缩为 WebP 格式,平均可减少 50% 体积。
2. 缩略图服务
使用 /img 接口按需生成缩略图,避免前端加载大图:
/img?id=xxx&w=200&h=200&f=webp&q=803. CDN 加速
将 /download 和 /img 接口接入CDN,提升全球访问速度。
4. 浏览器缓存
服务端返回 ETag 和 Last-Modified,支持304缓存。
5. 内存优化
使用 get_object_stream 流式读取大文件,避免内存溢出。
错误处理与重试机制
前端错误处理
- 文件过大:提示“文件大小不能超过 {0}M”
- 数量超限:提示“最多只能上传 {0} 张图片”
- 上传失败:
try...finally确保loading状态重置
后端错误处理
- 404:存储桶未找到
- 500:内部错误(如S3连接失败)
- 自动重试:
s3库内置重试机制
重试建议
前端可结合 uploadFile 封装重试逻辑,例如:
ts
async function uploadWithRetry(file, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await uploadFile(file);
} catch (err) {
if (i === retries - 1) throw err;
await sleep(1000 * (i + 1));
}
}
}本节来源