【问题标题】:Amazon S3 client could not download file with spaces or hash?Amazon S3 客户端无法下载带有空格或哈希的文件?
【发布时间】:2018-08-25 18:33:25
【问题描述】:

我正在使用AWSSDK.S3 版本3.3.17.2AWSSDK.Core 版本3.3.21.16 上传文件,然后下载相同的文件。下面的代码无法下载文件如果文件名有空格(或#

public class AmazonS3
{
    public async Task<string> UploadFileAsync(string sourceFile, string s3BucketUrl)
    {
        AmazonS3Uri s3Uri = new AmazonS3Uri(s3BucketUrl);
        using (var s3 = new AmazonS3Client(s3Uri.Region))
        {
            using (TransferUtility utility = new TransferUtility(s3))
            {
                TransferUtilityUploadRequest request = new TransferUtilityUploadRequest
                {
                    BucketName = s3Uri.Bucket,
                    ContentType = "application/pdf",
                    FilePath = sourceFile,
                    Key = s3Uri.Key + Path.GetFileName(sourceFile),
                };

                await utility.UploadAsync(request).ConfigureAwait(false);
            }
        }

        return Path.Combine(s3BucketUrl, Path.GetFileName(sourceFile));
    }  

    public async Task DownloadFileAsync(string destinationFilePath, string s3Url)
    {
        var s3Uri = new AmazonS3Uri(s3Url);
        var s3Client = new AmazonS3Client(s3Uri.Region);
        GetObjectRequest getObjectRequest = new GetObjectRequest
        {
            BucketName = s3Uri.Bucket,
            Key = s3Uri.Key
        };

        // dispose the underline stream when writing to local file system is done
        using (var getObjectResponse = await s3Client.GetObjectAsync(getObjectRequest).ConfigureAwait(false))
        {
            await getObjectResponse.WriteResponseStreamToFileAsync(destinationFilePath, false, default(System.Threading.CancellationToken)).ConfigureAwait(false);
        }
    }              
}

然后出于测试目的,我将上传文件并再次下载相同的文件

AmazonS3 s3 = new AmazonS3();

var uploadedFileS3Link = await s3.UploadFileAsync("C:\\temp\\my test file.pdf", @"https://mybucket.s3-us-west-2.amazonaws.com/development/test/");

// get exception at line below
await s3.DownloadFileAsync("C:\\temp\\downloaded file.pdf",uploadedFileS3Link );

我遇到了异常

Amazon.S3.AmazonS3Exception:指定的键不存在。 ---> Amazon.Runtime.Internal.HttpErrorResponseException:远程服务器 返回错误:(404) 未找到。 ---> System.Net.WebException: 远程服务器返回错误:(404)未找到。在 System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
在 System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func2 endFunction, Action1 endAction, Task1 promise, Boolean requiresSynchronization) --- 上一个堆栈跟踪的结束 抛出异常的位置---在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)在......

为简洁起见删除了剩余的异常

该文件确实存在于存储桶中。事实上,我可以复制并粘贴 s3url(即uploadedFileS3Link 变量的值)并通过浏览器下载文件。

(请注意,实际上我正在尝试下载 1000 多个已上传且名称中带有空格的文件。因此,在上传时删除空格不是一种选择)

更新 1 我注意到 S3 浏览器 Url 编码文件名

我尝试使用编码文件路径https://mybucket.s3-us-west-2.amazonaws.com/development/test/my%20test%20file.pdf 下载文件 但是还是不行

【问题讨论】:

    标签: amazon-s3 aws-sdk aws-sdk-net


    【解决方案1】:

    所以我终于找到了问题所在。我正在使用AmazonS3Uri 类来解析给定的 S3 url 并获取密钥、存储桶和区域。 AmazonS3Uri 将我的密钥返回为 development/test/my%20test%20file.pdf

    因为内部AmazonS3Uri 使用System.Uri 构建Uri,然后返回AbsolutePath,它将编码路径作为密钥返回(它应该返回本地路径作为密钥吗?

    我不知道为什么但是AmazonS3Client 不喜欢它,如果你传递编码键它会抛出异常。

    为了解决这个问题,我使用System.Net.WebUtility.UrlDecode(s3Uri.Key) 对密钥进行解码。所以新的下载方法看起来像

        public async Task DownloadFileAsync(string destinationFilePath, string s3Url)
        {
            var s3Uri = new S3UrlParser(s3Url);
            var s3Client = new AmazonS3Client(s3Uri.Region);
            GetObjectRequest getObjectRequest = new GetObjectRequest
            {
                BucketName = s3Uri.Bucket,
                Key = System.Net.WebUtility.UrlDecode(s3Uri.Key)
            };
    
            // dispose the underline stream when writing to local file system is done
            using (var getObjectResponse = await s3Client.GetObjectAsync(getObjectRequest).ConfigureAwait(false))
            {
                await getObjectResponse.WriteResponseStreamToFileAsync(destinationFilePath, false, default(System.Threading.CancellationToken)).ConfigureAwait(false);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-08-02
      • 2019-03-04
      • 2016-09-23
      • 1970-01-01
      • 2010-09-25
      • 2023-04-08
      相关资源
      最近更新 更多