Files
ljwx-chat/🚀立即修复上传问题.md
2025-11-29 07:36:44 +08:00

4.9 KiB
Raw Permalink Blame History

🚀 立即修复文件上传问题

📊 问题进展

✅ 第一个问题:网络错误 - 已解决

错误: "请确认你的网络是否正常" 原因: 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: 测试上传

  1. 访问: http://192.168.1.83:3210
  2. 打开开发者工具 (F12) → Network
  3. 上传一个文件
  4. ✅ 成功!

🔍 验证修复

检查预签名 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 使用 presignClient
    • createPreSignedUrlForPreview 使用 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

📚 详细文档

✅ 验证清单

  • 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