【问题标题】:Asp.Net Core File Upload on AWS ECS/EC2 in Container容器中 AWS ECS/EC2 上的 Asp.Net Core 文件上传
【发布时间】:2020-09-25 00:24:57
【问题描述】:

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

我们是否需要获取文件,将其保存到 S3,然后从那里处理?还是这只是一个配股?

【问题讨论】:

  • 您是否尝试过在本地运行 docker 容器,看看是否有同样的问题?
  • 文件上传上传到哪里?
  • 你让它工作了吗?你能分享任何对你有帮助的资源/文章吗?我在 aws 上使用 linux fargat 容器并尝试使用 .net 核心将文件写入 EC2 实例(文件共享)
  • 我们确实做到了,我将在下面添加解决方案。

标签: c# amazon-web-services amazon-s3 asp.net-core amazon-ecs


【解决方案1】:

使用 HostingEnvironment

private readonly IHostingEnvironment _hostingEnvironment;

public VehicleBrandController(ApplicationDbContext context, IHostingEnvironment hostingEnvironment)
{
    _context = context;
    _hostingEnvironment = hostingEnvironment;
}

记住使用 Path.Combine,如果使用传播或加号将字符串连接为路径,则不起作用。

public async Task UploadBrandImage()
{
    var uploadDir = Path.Combine(_hostingEnvironment.WebRootPath, "images/vehicle-icons");

    //If folder of new key is not exist, create the folder.
    if (!Directory.Exists(uploadDir)) Directory.CreateDirectory(uploadDir);

    foreach (var contentFile in Request.Form.Files)
    {
        var filePath = Path.Combine(_hostingEnvironment.WebRootPath, "images/vehicle-icons", contentFile.FileName);

        if (contentFile.Length <= 0) continue;

        // Using like this will not work
        //await contentFile.CopyToAsync(new FileStream($"{uploadDir}\\{contentFile.FileName}", FileMode.Create));

        using (var fileSteam = new FileStream(filePath, FileMode.Create))
        {
            await contentFile.CopyToAsync(fileSteam);
        }
    }
}

【讨论】:

    【解决方案2】:

    我们通过不在运行中保存它来实现它,我们将它保存为字节流,直到我们将它存储在 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')
    

    【讨论】:

      猜你喜欢
      • 2021-06-28
      • 1970-01-01
      • 2016-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-09
      • 2016-11-09
      • 1970-01-01
      相关资源
      最近更新 更多