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

使用AWS SDK向DigitalOcean Spaces传图遇Forbidden错误求助

使用AWS SDK向DigitalOcean Spaces上传图片时返回Forbidden错误

Error making request with Error Code Forbidden and Http Status Code Forbidden. No further error information was return.

问题代码

public async Task<bool> AddUserImage(ImageCreateDTO imageCreateDto)
{
    try
    {
        var credentials = new BasicAWSCredentials(_storageOptions.Value.AccessKey, _storageOptions.Value.SecretKey);

        AmazonS3Config config = new()
        {
            ServiceURL = _storageOptions.Value.ServiceUrl,
        };

        AmazonS3Client s3Client = new(
                _storageOptions.Value.AccessKey,
                _storageOptions.Value.SecretKey,
                config
                );
        using var stream = imageCreateDto.File.OpenReadStream();

        TransferUtility fileTransferUtility = new(s3Client);

        TransferUtilityUploadRequest fileTransferUtilityRequest = new()
        {
            BucketName = $"joinorcreate/{_storageOptions.Value.UserImages}",
            StorageClass = S3StorageClass.Standard,
            PartSize = imageCreateDto.File.Length,
            Key = imageCreateDto.FileName,
            CannedACL = S3CannedACL.PublicRead,
            InputStream = stream
        };

        // Add the x-amz-acl header
        fileTransferUtilityRequest.Headers["x-amz-acl"] = "public-read";

        await fileTransferUtility.UploadAsync(fileTransferUtilityRequest);

        // PutObjectRequest request = new()
        // {
        //     BucketName = $"joinorcreate/{_storageOptions.Value.UserImages}",
        //     Key = imageCreateDto.FileName,
        //     InputStream = stream,
        //     ContentType = imageCreateDto.File.ContentType,
        //     CannedACL = S3CannedACL.PublicRead,
        //     StorageClass = S3StorageClass.Standard,

        // };


        // await s3Client.PutObjectAsync(request);

        return true;
    }
    catch (AmazonS3Exception e)
    {
        Console.WriteLine(e.Message);
        return false;
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
        return false;
    }
}

需求

  1. 解决上传时的Forbidden错误
  2. 设置图片上传后默认权限为公开可读

错误修复及配置方案

1. 修正核心配置问题

检查凭证权限

确认你的DigitalOcean Spaces Access Key和Secret Key有效,且该密钥拥有写入(Write)和编辑权限(Edit Permissions)。在DigitalOcean控制台的Spaces页面,进入对应空间的API密钥管理界面,验证权限配置。

完善AmazonS3Config配置

DigitalOcean Spaces需要指定正确的区域并禁用路径样式访问,修改配置如下:

AmazonS3Config config = new()
{
    ServiceURL = _storageOptions.Value.ServiceUrl, // 格式示例:https://nyc3.digitaloceanspaces.com
    ForcePathStyle = false, // 必须设置为false,适配DigitalOcean的域名格式
    RegionEndpoint = RegionEndpoint.GetBySystemName("nyc3") // 替换为你的Spaces所在区域,如sfo3、ams3等
};

修正BucketName格式

DigitalOcean的BucketName仅为你的Spaces名称,目录结构需通过Key参数实现,而非拼接在BucketName中:

TransferUtilityUploadRequest fileTransferUtilityRequest = new()
{
    BucketName = "joinorcreate", // 直接使用Spaces名称
    StorageClass = S3StorageClass.Standard,
    PartSize = imageCreateDto.File.Length,
    Key = $"{_storageOptions.Value.UserImages}/{imageCreateDto.FileName}", // 目录路径+文件名
    CannedACL = S3CannedACL.PublicRead,
    InputStream = stream
};

移除重复ACL设置

已通过CannedACL = S3CannedACL.PublicRead设置公开权限,无需手动添加x-amz-acl头,删除以下代码:

// fileTransferUtilityRequest.Headers["x-amz-acl"] = "public-read";

2. 确保图片默认公开的两种方式

  • 代码层面:保持CannedACL = S3CannedACL.PublicRead配置,每次上传时自动设置文件为公开可读。
  • 控制台层面:在DigitalOcean控制台进入对应Spaces的设置页面,修改Default ACL为Public Read,此后所有新上传的文件默认权限均为公开,无需在代码中重复设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 06:45:55