English 中文(简体)
C# - 下载亚马孙S3桶的文档,在有水面时捕获错误
原标题:C# - Downloading a file from Amazon S3 bucket and catch error when it doesn t exist

I generate a list of filenames that I need to download from S3. Everything works fine but it breaks when it encounters a file that does not exist. When I try to list the contents of the bucket, I get an access denied error even though this should work fine, according to the vendor... so I gave up on trying to list contents.

Instead, is there a way I can just catch the error for the async method when it tries to download something that doesn t exist without it crashing my program? I d like to just move onto the next file in the list if one fails.

The error I get when I try a file that doesn t exist:

Amazon.S3.AmazonS3Exception: Access Denied --->   
Amazon.Runtime.Internal.HttpErrorResponseException: The remote server returned an error: (403) 
Forbidden. ---> System.Net.WebException: The remote server returned an error: (403) Forbidden. at 
System.Net.HttpWebRequest.GetResponse() at Amazon.Runtime.Internal.HttpRequest.GetResponse() --- 
End of inner exception stack trace 

My code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.Compression;
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.IO;
using System.Threading;

namespace AlgoSeekDecompressor
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<string>()
            {
                "Apple.csv",
                "Banana.csv",
                "Canteloupe.csv",
            };

            var downloadPath = @"E:My_Folder";

            Task.Run(async () => { await DownloadFilesAsync(list, downloadPath); }).Wait();

            Console.WriteLine("Done downloading");
        }

        static async Task DownloadFilesAsync(List<string> list, string downloadPath)
        {
            var accessKey = "#################";
            var secretAccessKey = "#########################";

            var client = new AmazonS3Client(
                accessKey,
                secretAccessKey,
                RegionEndpoint.USEast1
            );

            foreach (var file in list)
            {
                var bucketName = "amazon_s3_bucket";

                //There is a prefix that is the first letter of the filename
                var filename = file.Substring(0, 1).ToUpper() + "/" + file + ".csv.gz";

                var request = new GetObjectRequest()
                {
                    BucketName = bucketName,
                    Key = filename,
                    RequestPayer = RequestPayer.Requester
                };

                if (!Directory.Exists(downloadPath))
                {
                    Directory.CreateDirectory(downloadPath);
                    Console.WriteLine("Directory {0} does not exist - creating directory", downloadPath);
                }

                var filePath = Path.Combine(downloadPath, filename);
                var appendToFile = false;

                using (var response = await client.GetObjectAsync(request))
                {
                    await response.WriteResponseStreamToFileAsync(filePath, appendToFile, CancellationToken.None);
                }
            }
        }
    }
}
问题回答

我认为最好不要使用<代码>Task.Run,因为没有理由使用该代码,你只能直接使用你的方法。

About catching exceptions this would work:

static async Task Main(string[] args) {
    ///....

    var messages = await DownloadFilesAsync(list, downloadPath);

    if (!messages.Any())
      Console.WriteLine("Done");
    else
      Console.WriteLine("Some of files failed");
  }

  static async Task<List<string>> DownloadFilesAsync(List < string > list, string downloadPath) {
    //....

    var errorMessages = new List<string>();
    foreach(var file in list) {
      //.....

      var filePath = Path.Combine(downloadPath, filename);
      var appendToFile = false;

      using GetObjectResponse response = await client.GetObjectAsync(request);

      try {

        await response.WriteResponseStreamToFileAsync(filePath, appendToFile, CancellationToken.None);

        if(response.HttpStatusCode != System.Net.HttpStatusCode.OK)
            errorMessages.Add($"Failed to download {objectName} with status {response.HttpStatusCode}");

      } 
     catch (AmazonS3Exception ex) {

        errorMessages.Add($"Error saving {objectName}: {ex.Message}");
      }

     catch (Exception ex) {

        errorMessages.Add($"Unhandled exception on saving {objectName}: {ex.Message}");
      }
    }

    return errorMessages;
  }




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签