首页 > 解决方案 > 容器中 AWS ECS/EC2 上的 Asp.Net Core 文件上传

问题描述

我有一个 asp .net 核心应用程序在 docker linux 容器中部署到 AWS,在 ECS 中托管到 EC2 服务器(不是 Fargate)中。我们有一个 React 前端 UI,它将文件上传到 .net 核心 api,然后我们对其进行处理。这在开发中正常工作,但是,在产品中,文件上传失败,我认为服务器没有访问/权限将文件保存到我们的上传文件夹(想想 webapproot/upload)。

我们是否需要获取文件,将其保存到 S3,然后从那里处理?或者这仅仅是一个权利问题?

标签: c#amazon-web-servicesamazon-s3asp.net-coreamazon-ecs

解决方案


我们通过不在运行中保存它来实现它,我们将它保存为字节流,直到我们将它存储在 S3 存储桶中。请注意,您需要确保使用IFormFileCollection并确保在启动应用程序时包含您的机密,并在 CI/CD 中告诉 aws 包括来自 Secrets Manager 的机密(假设您将它们托管在那里)。

端点:

    [HttpPost]
    [Consumes("multipart/form-data")]
    [RequestSizeLimit(int.MaxValue)]
    public async Task<IActionResult> Post([FromForm]IFormFileCollection files, [FromForm]FileTypes fileType)
    {
        try
        {
            long size = files.Sum(f => f.Length);

            var fileName = string.Empty;

            foreach (var formFile in files)
            {
                if (formFile.Length > 0)
                {
                    fileName = $"{fileType.ToString()}-{Guid.NewGuid().ToString()}";

                    await _mediator.Send(new S3Messages.Save(formFile.OpenReadStream(), "fileimport", fileName));
                }
            }

            return Ok(new FileUploadResponse
            {
                Count = files.Count,
                Size = size,
                Files = files.Select(f => new ImportFile()
                {
                    Created = DateTime.Now,
                    FileName = fileName,
                    FileSize = size,
                    FileTypeID = (int)fileType,
                }),
            });
        }
        catch (Exception ex)
        {
            return BadRequest(ex.Message);
        }
    }

程序.cs:

      public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((context, config) =>
                {
                    config.AddUserSecrets<Startup>();

                    if (context.HostingEnvironment.IsProduction())
                    {
                        config.AddEnvironmentVariables();

                        var secretsJson = Secrets.Get("us-east-1");

                        var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(secretsJson);

                        config.AddInMemoryCollection(dict);
                    }
                })
                .UseServiceProviderFactory(new ServiceProviderFactory<Program>())
                .ConfigureWebHostDefaults(builder =>
                {
                    builder
                        .UseUrls("http://*:5000")
                        .UseStartup<Startup>();
                });

ci/cd 管道 yaml 文件,确保在创建任务时带入秘密:

- export TASK_VERSION=$(aws ecs register-task-definition --family "${ECS_TASK_NAME}" --network-mode host --execution-role-arn "xxx" --container-definitions "[{\"name\":\"$PROJECT_NAME\",\"image\":\"$IMAGE_NAME\",\"portMappings\":[{\"containerPort\":5000,\"hostPort\":5000,\"protocol\":\"tcp\"}],\"memoryReservation\":512,\"memory\":2004,\"essential\":true,\"environment\":[{\"name\":\"SECRETS_NAME\",\"value\":\"$xxx_SECRETS_NAME\"}],\"secrets\":[{\"name\":\"$xxx_SECRETS_NAME\",\"valueFrom\":\"$xxx_SECRETS\"}]}]" | jq --raw-output '.taskDefinition.revision')

推荐阅读