我正在使用 AWSSDK.S3
版本3.3.17.2
和 AWSSDK.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 );
我得到了异常(exception)
Amazon.S3.AmazonS3Exception: The specified key does not exist. ---> Amazon.Runtime.Internal.HttpErrorResponseException: The remote server returned an error: (404) Not Found. ---> System.Net.WebException: The remote server returned an error: (404) Not Found. at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
at System.Threading.Tasks.TaskFactory1.FromAsyncCoreLogic(IAsyncResult iar, Func
2 endFunction, Action1 endAction, Task
1 promise, Boolean requiresSynchronization) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at ......
为简洁起见删除了剩余的异常(exception)
该文件确实存在于存储桶中。事实上,我可以复制并粘贴 s3url(即
uploadedFileS3Link
变量的值)并通过浏览器下载文件。(请注意,实际上我正在尝试下载 1000 多个已上传的文件,这些文件的名称中带有空格。因此在上传时删除空格不是一种选择)
更新 1
我注意到 S3 浏览器 Url 编码文件名
我尝试使用编码文件路径
https://mybucket.s3-us-west-2.amazonaws.com/development/test/my%20test%20file.pdf
下载文件但它仍然不起作用
最佳答案
所以最后我发现了问题所在。我正在使用 AmazonS3Uri类来解析给定的 S3 url 并获取 key 、存储桶和区域。 AmazonS3Uri
将我的 key 返回为 development/test/my%20test%20file.pdf
因为内部AmazonS3Uri
正在使用 System.Uri
构建 Uri 然后返回 AbsolutePath
它返回编码路径作为键(它应该返回本地路径作为键吗?)
我不知道为什么但AmazonS3Client
不喜欢它,如果您传递 Encoded key ,它会抛出异常。
所以为了解决这个问题,我使用 System.Net.WebUtility.UrlDecode(s3Uri.Key)
解码 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);
}
}
关于amazon-s3 - Amazon S3 客户端无法下载带有空格或散列的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49325019/