前端处理方案
图片预处理
- 压缩优化:使用Luban、Glide等库进行图片压缩(如WebP格式转换)
- 质量调整:通过BitmapFactory.Options设置inSampleSize进行分辨率缩放
- 格式转换:统一转换为JPEG/PNG格式,建议使用FileProvider处理URI权限
多图选择方案
实现方式 |
适用场景 |
优点 |
缺点 |
系统相册多选 |
普通APP |
原生体验好 |
需处理不同厂商适配 |
RecyclerView自定义 |
特殊需求 |
可定制性强 |
开发成本高 |
第三方库(如PhotoPicker) |
快速开发 |
开箱即用 |
功能可能冗余 |
上传策略
// 分片上传示例(OkHttp)
public void uploadImage(File file) {
int chunkSize = 210241024; // 2MB分片
byte[] buffer = new byte[chunkSize];
try (FileInputStream fis = new FileInputStream(file)) {
int read;
while ((read = fis.read(buffer)) != -1) {
RequestBody body = RequestBody.create(buffer, 0, read);
okHttpClient.newCall(Request.post(uploadUrl).body(body)).execute();
}
} catch (IOException e) {
// 错误处理逻辑
}
}
后端接收方案
主流框架实现
- Spring Boot:
@PostMapping("/upload")
public ResponseEntity handleFile(@RequestParam MultipartFile file) {
String path = "/upload/" + UUID.randomUUID() + ".jpg";
file.transferTo(new File(serverPath + path));
return ResponseEntity.ok(path);
}
- Node.js (Multer):
const upload = multer({ dest: 'uploads/' });
app.post('/upload', upload.array('files'), (req, res) => {
req.files.forEach(file => {
// 文件校验和存储逻辑
});
res.send({ status: 'success' });
});
存储方案对比
存储类型 |
成本 |
性能 |
适用场景 |
本地文件系统 |
低 |
高 |
小团队快速部署 |
AWS S3 |
中 |
高 |
中大型项目 |
阿里云OSS |
中 |
高 |
国内项目 |
MongoDB GridFS |
中 |
中 |
非结构化数据 |
关键优化技术
断点续传实现
- 客户端:记录已上传分片的ETag
- 服务端:校验MD5并返回唯一标识
- 状态机:维护上传进度(已上传/待上传/失败重试)
并发控制策略
# Python异步处理示例
from aiohttp import web
async def handle_upload(request):
data = await request.post()
tasks = [save_file(f) for f in data['files']]
await asyncio.gather(tasks)
return web.Response(text="Success")
安全加固措施
- 验证层:
- 文件头校验(Magic Number检测)
- MIME类型白名单(如image/jpeg)
- 客户端签名验证(HMAC-SHA256)
- 存储层:
- 隔离上传目录(Linux chroot)
- 设置文件读写权限(chmod 644)
- 干扰扫描(ClamAV集成)
常见问题解决方案
问题现象 |
解决方案 |
技术实现 |
大文件上传失败 |
分片+并行上传 |
前端WebWorker切片,后端合并临时文件 |
网络波动导致中断 |
断点续传机制 |
客户端本地缓存进度,服务端记录上传状态 |
多用户并发冲突 |
分布式锁 |
Redis分布式锁或数据库乐观锁 |
存储空间不足 |
自动扩容机制 |
云存储弹性扩容或本地LVM管理 |
性能监控指标
监控项 |
阈值 |
优化手段 |
单文件上传耗时 |
>3s |
CDN加速/DNS预解析 |
CPU使用率 |
>80% |
异步处理/负载均衡 |
磁盘IO等待 |
>50% |
SSD硬盘/RAID阵列 |
内存占用 |
>70% |
对象存储替代本地文件系统 |
【相关问题与解答】
Q1:如何实现上传过程中的实时进度显示?
A1:采用事件驱动架构,在OkHttp客户端使用newProgressListener
监听数据写入进度,通过Handler更新UI进度条,服务端需支持持续连接或长轮询推送进度信息。
Q2:如何处理海量小文件并发上传的场景?
A2:采用消息队列削峰填谷(如Kafka),将上传请求异步化,使用对象存储服务(如MinIO)的批量操作接口,结合LevelDB进行元数据缓存,最终通过分布式任务调度完成