Files
1818web-hoduan/docs/admin-oss-upload-bug-fix-detail.md
2025-11-14 17:41:15 +08:00

5.9 KiB
Raw Blame History

管理端OSS上传字段名Bug修复详解

🐛 问题详细分析

错误现象

<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>user_img/covers/82D78B6D-B229-0C7B-2567-C023C0386A0A.png</Key>
</Error>

问题根源

虽然后端成功生成了OSS签名但前端上传时使用了错误的FormData字段名导致文件实际上没有上传到OSS。


🔍 字段名对照表

错误的字段名(我们文档中的错误示例)

// 错误示例 - 不要使用这些字段名
formData.append('OSSAccessKeyId', signature.accessKeyId);        // ❌ 错误
formData.append('signature', signature.signature);              // ❌ 错误  
formData.append('x-oss-signature-version', signature.version);  // ❌ 错误

正确的字段名OSS POST 签名 V4 要求)

// 正确示例 - 必须使用这些字段名
formData.append('key', objectKey);                                    // ✅ 文件路径
formData.append('policy', signature.policy);                         // ✅ 策略
formData.append('x-oss-credential', signature.x_oss_credential);     // ✅ 凭证
formData.append('x-oss-date', signature.x_oss_date);                 // ✅ 日期
formData.append('x-oss-signature-version', signature.x_oss_signature_version); // ✅ 版本
formData.append('x-oss-signature', signature.x_oss_signature);       // ✅ 签名
formData.append('success_action_status', '200');                     // ✅ 成功状态
formData.append('file', file);                                       // ✅ 文件

🔧 修复内容

1. 修正后端返回字段名

文件: AdminOssServiceImpl.java

// 修复前
response.put("version", "OSS4-HMAC-SHA256");
response.put("signature", signature);

// 修复后  
response.put("x_oss_signature_version", "OSS4-HMAC-SHA256");
response.put("x_oss_signature", signature);

2. 创建测试页面

文件: test_admin_oss_upload.html

功能特性:

  • 🔐 管理员Token验证
  • 📁 多种上传目录选择
  • 🔄 新版/兼容接口切换
  • 📊 实时上传进度
  • 🐛 详细调试信息
  • 文件访问测试

3. 修正文档示例

更新所有文档中的前端上传代码示例。


🚀 正确的上传流程

步骤1: 获取上传签名

const response = await fetch('/admin/oss/post-signature', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${adminToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    fileName: file.name,
    directory: 'covers',
    maxSizeMB: 50
  })
});

const result = await response.json();
const signature = result.data;

步骤2: 构建FormData关键步骤

const formData = new FormData();

// 生成唯一文件名避免冲突
const uniqueFileName = `${Date.now()}_${Math.random().toString(36).substring(2)}_${file.name}`;
const objectKey = `${signature.dir}${uniqueFileName}`;

// 按OSS要求添加字段 - 字段名必须准确!
formData.append('key', objectKey);
formData.append('policy', signature.policy);
formData.append('x-oss-credential', signature.x_oss_credential);
formData.append('x-oss-date', signature.x_oss_date);
formData.append('x-oss-signature-version', signature.x_oss_signature_version);
formData.append('x-oss-signature', signature.x_oss_signature);
formData.append('success_action_status', '200');
formData.append('file', file);

步骤3: 上传到OSS

const uploadResponse = await fetch(signature.host, {
  method: 'POST',
  body: formData
});

if (uploadResponse.ok) {
  const fileUrl = `${signature.host}/${objectKey}`;
  console.log('上传成功:', fileUrl);
}

🧪 测试验证

使用测试页面

  1. 访问 /test_admin_oss_upload.html
  2. 输入管理员Token
  3. 选择文件和目录
  4. 点击"生成上传签名"
  5. 点击"上传文件到OSS"
  6. 点击"测试文件访问"

预期结果

  • 签名生成成功
  • 文件上传到OSS成功
  • 文件URL可正常访问
  • 不再出现NoSuchKey错误

🛡️ 常见问题排查

问题1: 仍然提示NoSuchKey

可能原因:

  • 前端仍在使用错误的字段名
  • 文件名包含特殊字符
  • OSS权限配置问题

解决方案:

// 检查FormData字段名是否正确
console.log('FormData字段:');
for (let pair of formData.entries()) {
    console.log(pair[0], ':', pair[1]);
}

问题2: 签名生成失败

可能原因:

  • Token无效或过期
  • 权限不足
  • 文件类型不支持

解决方案:

// 检查Token和权限
const token = localStorage.getItem('adminToken');
console.log('当前Token:', token);

问题3: 上传进度卡住

可能原因:

  • 网络连接问题
  • 文件过大
  • OSS服务异常

解决方案:

// 添加超时处理
const controller = new AbortController();
setTimeout(() => controller.abort(), 60000); // 60秒超时

fetch(signature.host, {
  method: 'POST',
  body: formData,
  signal: controller.signal
});

📚 相关文档更新

以下文档已同步更新正确的字段名:


🎯 总结

修复效果

  1. 字段名正确: 使用OSS规范的字段名
  2. 上传成功: 文件能正确上传到OSS
  3. 访问正常: 上传后的文件URL可正常访问
  4. 测试工具: 提供完整的测试页面

🚨 重要提醒

  1. 字段名必须准确: OSS对字段名大小写敏感
  2. 文件名唯一: 建议使用时间戳+随机数避免覆盖
  3. 错误处理: 做好网络异常和上传失败的处理
  4. 调试信息: 使用测试页面查看详细的调试信息

修复状态: 已完成
测试状态: 已验证
文档状态: 已同步
风险等级: 低(不影响现有功能)