You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DigitalOcean Spaces预签名Put URL跨域凭证配置错误求助

问题:DigitalOcean Spaces预签名Put URL的CORS凭证头异常

使用预签名Put URL给React前端实现文件上传时,遇到CORS错误:DigitalOcean返回的Access-Control-Allow-Credentials头值为空字符串,而非预期的true。

服务端S3客户端配置(Node.js)

const { PutObjectCommand, S3Client } = require('@aws-sdk/client-s3');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');

const { config } = require('../../config/environments');

const { doKey, doSecret } = config;

const s3 = new S3Client({
  endpoint: 'https://chatty-bucket.fra1.digitaloceanspaces.com',
  credentials: {
    accessKeyId: doKey,
    secretAccessKey: doSecret,
  },
  region: 'fra1',
});

const generatePresignedUrl = async (fileType, fileName) => {
  try {
    const command = new PutObjectCommand({
      Bucket: '_static',
      Key: fileName,
      ACL: 'public',
    });

    const url = await getSignedUrl(s3, command, {
      expiresIn: 3600,
    });

    return url;
  } catch (error) {
    return error;
  }
};

module.exports = { generatePresignedUrl };

前端Axios请求代码

await axios.put(data?.data.data.url, files[0], {
        headers: {
          'Content-Type': files[0].type,
          'Content-Length': new Blob([files[0]]).length,
          'x-amz-acl': 'public-read',
          'Access-Control-Allow-Origin': 'http://localhost:5173',
        },
        withCredentials: true,
      });

相关信息

  • 请求发起自本地localhost:5173
  • 已配置存储桶CORS规则

解决方法
  • 移除前端无效请求头
    前端不要手动设置Access-Control-Allow-Origin,该头由服务端返回,前端设置无效且可能干扰CORS校验。同时Content-Length无需手动指定,Axios会自动处理:

    await axios.put(data?.data.data.url, files[0], {
      headers: {
        'Content-Type': files[0].type,
        'x-amz-acl': 'public-read',
      },
      // 预签名URL已包含认证信息,无需携带额外凭证,可删除此行
      // withCredentials: true,
    });
    
  • 修正存储桶CORS配置
    确保CORS规则中明确开启AllowCredentials: true,且指定具体允许的Origin(使用*时无法开启凭证),示例配置:

    [
      {
        "AllowedHeaders": ["*"],
        "AllowedMethods": ["PUT"],
        "AllowedOrigins": ["http://localhost:5173"],
        "AllowCredentials": true,
        "ExposeHeaders": []
      }
    ]
    
  • 统一ACL配置
    服务端PutObjectCommand中的ACL值与前端x-amz-acl保持一致,避免权限冲突:

    const command = new PutObjectCommand({
      Bucket: '_static',
      Key: fileName,
      ACL: 'public-read', // 与前端x-amz-acl值统一
    });
    
  • 确认凭证必要性
    预签名URL本身已包含临时认证信息,跨域请求无需开启withCredentials: true,若强制开启,需确保CORS配置的AllowCredentials为true且Origin非通配符。


内容的提问来源于stack exchange,提问作者Mustafa Salem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 21:45:33