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

如何在ASP.NET Core后端获取AWS上传链接实现S3直传?

在ASP.NET Core中生成AWS S3预签名URL实现客户端直传

核心逻辑是后端通过AWS SDK生成预签名URL,客户端拿到这个URL后直接向S3发起PUT请求上传文件,无需经过后端中转。以下是具体实现步骤:

1. 准备工作

  • 安装AWS S3 SDK NuGet包:Install-Package AWSSDK.S3
  • 在appsettings.json中配置AWS相关参数(生产环境建议用EC2/EKS的IAM角色,避免硬编码密钥):
"AWS": {
  "Profile": "your-aws-profile",
  "Region": "your-s3-region",
  "BucketName": "your-bucket-name"
}

2. 注册AWS服务

在Program.cs中添加S3客户端的依赖注入:

builder.Services.AddAWSService<IAmazonS3>();

3. 实现预签名URL生成服务

创建一个服务类来封装S3操作逻辑:

public interface IS3PresignedUrlService
{
    Task<string> GeneratePresignedUploadUrlAsync(string fileName);
}

public class S3PresignedUrlService : IS3PresignedUrlService
{
    private readonly IAmazonS3 _s3Client;
    private readonly IConfiguration _configuration;

    public S3PresignedUrlService(IAmazonS3 s3Client, IConfiguration configuration)
    {
        _s3Client = s3Client;
        _configuration = configuration;
    }

    public async Task<string> GeneratePresignedUploadUrlAsync(string fileName)
    {
        var bucketName = _configuration["AWS:BucketName"];
        // 建议给文件名加前缀或UUID避免重复,比如:uploads/{Guid.NewGuid()}_{fileName}
        var objectKey = $"uploads/{Guid.NewGuid()}_{fileName}";

        var request = new GetPreSignedUrlRequest
        {
            BucketName = bucketName,
            Key = objectKey,
            Expires = DateTime.UtcNow.AddMinutes(15), // URL有效期,按需调整
            Verb = HttpVerb.PUT,
            // 如果需要设置文件类型,添加ContentType
            ContentType = "image/jpeg" // 根据实际上传的图片类型调整,或者由前端传入
        };

        return await Task.FromResult(_s3Client.GetPreSignedURL(request));
    }
}

然后在Program.cs中注册这个服务:

builder.Services.AddScoped<IS3PresignedUrlService, S3PresignedUrlService>();

4. 编写API接口

创建一个API控制器来提供预签名URL:

[ApiController]
[Route("api/s3")]
public class S3Controller : ControllerBase
{
    private readonly IS3PresignedUrlService _presignedUrlService;

    public S3Controller(IS3PresignedUrlService presignedUrlService)
    {
        _presignedUrlService = presignedUrlService;
    }

    [HttpGet("upload-url")]
    public async Task<IActionResult> GetUploadUrl([FromQuery] string fileName)
    {
        if (string.IsNullOrEmpty(fileName))
        {
            return BadRequest("文件名不能为空");
        }

        var url = await _presignedUrlService.GeneratePresignedUploadUrlAsync(fileName);
        return Ok(new { UploadUrl = url });
    }
}

5. 客户端上传示例(前端JS)

拿到后端返回的UploadUrl后,直接发起PUT请求:

async function uploadFileToS3(file, uploadUrl) {
    const response = await fetch(uploadUrl, {
        method: 'PUT',
        body: file,
        headers: {
            'Content-Type': file.type // 要和后端设置的ContentType一致
        }
    });
    return response.ok;
}

关键注意事项

  • CORS配置:必须在S3桶的CORS规则中允许PUT请求,否则客户端会跨域失败。示例CORS规则:
<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin> <!-- 生产环境限制为你的前端域名 -->
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
  </CORSRule>
</CORSConfiguration>
  • 权限控制:确保生成预签名URL的AWS账号/角色拥有s3:PutObject权限;如果需要控制文件访问,可设置预签名URL的有效期,或者在S3中配置对象的ACL。
  • 文件名处理:避免直接使用用户上传的文件名,防止覆盖已有文件,建议添加唯一标识(如UUID)作为前缀。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 03:05:20