4.9 KiB
4.9 KiB
🚀 立即修复文件上传问题
📊 问题进展
✅ 第一个问题:网络错误 - 已解决
错误: "请确认你的网络是否正常" 原因: MinIO 未启动 解决: 已启动 MinIO 服务
🔧 第二个问题:403 Forbidden - 需要修复
错误: "Forbidden" 原因: 预签名 URL 签名失效 解决: 修改代码,使用双客户端架构
🎯 最新修复方案
核心改进
创建两个独立的 S3Client:
class S3 {
private client: S3Client; // 使用 S3_ENDPOINT - 内部操作
private presignClient: S3Client; // 使用 S3_PUBLIC_DOMAIN - 生成预签名 URL
}
优势:
- ✅ 内部操作使用容器可访问的地址
- ✅ 预签名 URL 使用浏览器可访问的地址
- ✅ 签名基于正确的 endpoint,不会失效
🚀 立即修复(3 步)
步骤 1: 重新构建镜像
./rebuild-and-restart.sh
或者手动执行:
docker-compose -f docker-compose.lingjingwanxiang.yml down
docker build -t lingjingwanxiang:latest .
docker-compose -f docker-compose.lingjingwanxiang.yml up -d
预计时间: 5-10 分钟
步骤 2: 等待启动完成
docker logs -f lingjingwanxiang
看到以下信息表示启动成功:
▲ Next.js 15.x.x
- Local: http://localhost:3210
✓ Ready in XXs
步骤 3: 测试上传
- 访问: http://192.168.1.83:3210
- 打开开发者工具 (F12) → Network
- 上传一个文件
- ✅ 成功!
🔍 验证修复
检查预签名 URL
在 Network 标签中查看:
✅ 正确的 URL:
http://192.168.1.83:9002/lingjingwanxiang/files/xxx?X-Amz-Algorithm=...&X-Amz-Signature=...
❌ 错误的 URL:
http://host.docker.internal:9002/... (浏览器无法访问)
检查上传请求
PUT 请求应该:
- URL:
http://192.168.1.83:9002/... - Status:
200 OK - Response Headers 包含
ETag
⚠️ 常见问题
Q1: 构建失败 "no space left on device"
# 清理 Docker 空间
docker system prune -a -f
# 检查磁盘空间
df -h
Q2: 仍然返回 403
# 1. 确认重新构建了镜像
docker images | grep lingjingwanxiang
# 2. 检查环境变量
docker exec lingjingwanxiang printenv | grep S3_PUBLIC_DOMAIN
# 应该输出: S3_PUBLIC_DOMAIN=http://192.168.1.83:9002
# 3. 重启容器
docker-compose -f docker-compose.lingjingwanxiang.yml restart
Q3: 网络错误又出现了
# 检查 MinIO 是否运行
docker ps | grep minio
# 如果没有运行,启动 MinIO
docker-compose -f docker-compose.minio.yml up -d
Q4: CORS 错误
# 重新配置 CORS
./setup-minio.sh
📝 修改的文件
核心修复
- ✅
src/server/modules/S3/index.ts- 添加
presignClient属性 - 修改构造函数创建两个客户端
createPreSignedUrl使用presignClientcreatePreSignedUrlForPreview使用presignClient
- 添加
测试更新
- ✅
src/server/modules/S3/index.test.ts- 更新测试用例以验证新架构
🎓 技术原理
为什么需要两个客户端?
| 场景 | 使用的客户端 | Endpoint | 访问者 |
|---|---|---|---|
| 上传 / 删除文件 | client |
host.docker.internal:9002 |
容器内部 |
| 生成预签名 URL | presignClient |
192.168.1.83:9002 |
浏览器 |
错误方案 vs 正确方案
❌ 错误方案(之前的修复):
// 生成 URL 后替换域名 → 破坏签名
const url = await getSignedUrl(client, command);
return url.replace('host.docker.internal', '192.168.1.83');
✅ 正确方案(当前修复):
// 使用正确的 endpoint 生成 URL → 签名正确
return getSignedUrl(presignClient, command);
AWS 签名机制
AWS Signature V4 包括:
- HTTP 方法
- 完整 URL(包括 host) ← 关键
- Headers
- Payload
修改 URL 会导致签名失效 → 403 Forbidden
📚 详细文档
- 修复 403 错误.md - 技术细节
- 文件上传故障排查.md - 完整排查指南
✅ 验证清单
- Docker 镜像已重新构建
- 容器启动成功
- MinIO 运行正常
- 预签名 URL 包含
192.168.1.83:9002 - 文件上传成功(200 OK)
- 上传的文件可以在聊天中显示
🆘 需要帮助?
如果按照上述步骤仍然失败,提供以下信息:
# 1. 容器状态
docker ps -a
# 2. 应用日志
docker logs lingjingwanxiang > app.log
# 3. MinIO 日志
docker logs lingjingwanxiang-minio > minio.log
# 4. 环境变量
docker exec lingjingwanxiang printenv > env.log
# 5. 诊断测试
./test-upload.sh > diagnostic.log
然后将这些日志文件发送给我。
准备好了吗?执行下面的命令开始修复!
./rebuild-and-restart.sh