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

使用S3底层API(PutObjectRequest)批量上传文件仅执行一次的问题排查

问题描述

我是AWS和.NET新手,正对比PutObjectRequest与Transfer Utility在不同数据大小及参数下的性能,计划上传10个文件并比较耗时。我尝试了如下代码:

DirectoryInfo place = new DirectoryInfo(@"D:\Files\256KB");
FileInfo[] Files = place.GetFiles();

foreach (FileInfo file in Files)
{
    var str = file.Name;
    string destinationPath = Path.Combine(directoryName, str);
    if (destinationPath.Length > 0)
    {
        var s3LocationForUploadData = "uploadir";
        PutObject(destinationPath, s3LocationForUploadData);
    }
}


public void PutObject(string filePathStreamToSave, string objectKeyForFile)
{
    try
    {
        var putRequest = new PutObjectRequest
        {
            BucketName = Bucket,
            Key = objectKeyForFile,
            FilePath = filePathStreamToSave  
        };

        Stopwatch sw = new Stopwatch();
        sw.Start();
        PutObjectResponse response = s3Client.PutObjectAsync(putRequest).GetAwaiter().GetResult();
        sw.Stop();
        Console.WriteLine("TIME ELAPSED:"+sw.Elapsed);
        Console.ReadLine();
    }
    catch (AmazonS3Exception e)
    {
        Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object",e.Message);
    }
}

但foreach循环中的PutObject调用仅执行一次,请问如何实现触发每个文件的PutObjectAsync调用?

解决方案

问题根源

你的代码里PutObject方法最后有Console.ReadLine(),第一次上传完成后程序会停在这里等待用户输入,导致foreach循环无法继续执行后续文件的上传。

修复步骤

  1. 移除Console.ReadLine():把PutObject方法里的Console.ReadLine()删掉,上传完一个文件后会自动回到循环处理下一个文件。
  2. 优化异步调用方式:不要用.GetAwaiter().GetResult()阻塞线程,改成标准的async/await模式,避免线程死锁风险,同时让异步操作更符合最佳实践。

修改后的代码示例:

DirectoryInfo place = new DirectoryInfo(@"D:\Files\256KB");
FileInfo[] Files = place.GetFiles();

// 调用异步上传方法
await UploadFilesAsync(Files);

// 异步封装文件上传逻辑
public async Task UploadFilesAsync(FileInfo[] files)
{
    foreach (FileInfo file in files)
    {
        var str = file.Name;
        string destinationPath = Path.Combine(directoryName, str);
        if (destinationPath.Length > 0)
        {
            var s3LocationForUploadData = "uploadir";
            await PutObjectAsync(destinationPath, s3LocationForUploadData);
        }
    }
}

public async Task PutObjectAsync(string filePathStreamToSave, string objectKeyForFile)
{
    try
    {
        var putRequest = new PutObjectRequest
        {
            BucketName = Bucket,
            Key = objectKeyForFile,
            FilePath = filePathStreamToSave  
        };

        Stopwatch sw = new Stopwatch();
        sw.Start();
        PutObjectResponse response = await s3Client.PutObjectAsync(putRequest);
        sw.Stop();
        Console.WriteLine($"文件 {objectKeyForFile} 上传耗时: {sw.Elapsed}");
    }
    catch (AmazonS3Exception e)
    {
        Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message);
    }
}

额外性能测试建议

  • 多次运行测试取平均值,避免单次网络波动干扰结果
  • 可尝试并行上传(比如Task.WhenAll),但需注意AWS S3的并发请求限制
  • 分批次测试不同大小的文件(如256KB、1MB、10MB等),记录各场景的耗时差异

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:36:05