使用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循环无法继续执行后续文件的上传。
修复步骤
- 移除
Console.ReadLine():把PutObject方法里的Console.ReadLine()删掉,上传完一个文件后会自动回到循环处理下一个文件。 - 优化异步调用方式:不要用
.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
相关产品推荐
相关产品推荐

