如何在不使用 SDK 的情况下使用 .NET HttpClient 上传到 Amazon S3
Posted
技术标签:
【中文标题】如何在不使用 SDK 的情况下使用 .NET HttpClient 上传到 Amazon S3【英文标题】:How do I upload to Amazon S3 using .NET HttpClient WITHOUT using their SDK 【发布时间】:2015-04-30 17:42:49 【问题描述】:如何仅使用 .NET 的 HttpClient(或 WebClient)将文件上传到 Amazon S3 上的存储桶?必须使用“PUT”来完成。
我可以使用亚马逊的 AWS 开发工具包进行上传,但我想知道如何在没有它的情况下进行上传。我看了他们的文档好几个小时了,还是没明白。
任何帮助将不胜感激。
我使用他们的 SDK 的代码是:
public static void TestPutObjectAsync()
AmazonS3Client client = new AmazonS3Client();
client.AfterResponseEvent += new ResponseEventHandler(callback);
PutObjectRequest request = new PutObjectRequest
BucketName = BUCKET_NAME,
Key = "Item1",
FilePath = FILE_PATH,
;
client.PutObjectAsync(request);
public static event EventHandler UploadComplete;
public static void callback(object sender, ResponseEventArgs e)
if (UploadComplete != null)
UploadComplete(sender, e);
【问题讨论】:
您有什么更好的方法可以在不使用 .net sdk 的情况下将文件上传到 s3 吗? 【参考方案1】:我在尝试在 Xamarin .net 核心跨平台客户端中部署文件上传时遇到了这个问题,其中预签名的帖子是使用 boto3 在服务器端生成的。
要求是不要使用 SDK 客户端,因为虽然这个问题是关于 AWS S3,但许多其他服务(Wasabi 和 Digital Ocean 仅举几例)使用相同的 API 和 SDK 客户端的配置不同的服务可能难以管理——服务器应该处理为各种服务端点生成预签名的 POST,而客户端不应该镜像该端点。这样,我们的服务器可以轻松更改端点,而客户端不需要更新。
1:为预签帖创建支持模型。这源于https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3.html#generating-presigned-posts
public class PresignedPost
public string url get; set;
public Fields fields get; set;
public class Fields
public string AWSAccessKeyId get; set;
public string acl get; set;
public string key get; set;
public string policy get; set;
public string signature get; set;
2:加载文件。在我们的例子中,我们通过
读入内存string data = File.ReadAllText(filepath)
是的,这可能会导致内存中的大文件出现问题,但目前我们的要求中并未解决此限制。
3:使用 System.Net.Http 中的 HttpClient 创建 Upload 方法
public static async Task<bool> Upload(PresignedPost presignedPost, string data)
using (HttpClient client = new HttpClient())
try
MultipartFormDataContent formData = new MultipartFormDataContent
new StringContent(presignedPost.fields.acl), "acl" ,
new StringContent(presignedPost.fields.AWSAccessKeyId), "AWSAccessKeyId" ,
new StringContent(presignedPost.fields.key), "key" ,
new StringContent(presignedPost.fields.policy), "policy" ,
new StringContent(presignedPost.fields.signature), "signature" ,
new StringContent(data), "file" ,
;
var response = await client.PostAsync(presignedPost.url, formData);
//if response is 204 no content it's successful
if (response.StatusCode == HttpStatusCode.NoContent)
return true;
catch (Exception ex)
//do something with exception
return false;
评论:
1:也可以将文件加载为字节数组,然后使用 formData 中的内存流。这在上传较大的文件时可能会有所帮助,但是,我们的堆栈首先加密文件并返回一个字符串,因此我们在此实现中没有选择该方法。参考:C# HttpClient 4.5 multipart/form-data upload 或者简单地使用字节数组而不是字符串 ref:send byte array by HTTP POST in store app
2:您可能会注意到,我们假设 204 响应代码表示上传成功。虽然这显然很危险,但我们找不到任何关于为什么会发生这种情况的文档 - 也许这与 AWS S3 Object DELETE 也返回 204 的原因相同。如果您担心这一点,您可以添加一个 API 调用来检查如果文件存在。
3:是的,有关于使用“使用”处理 HttpClients 的争论,您可以根据您的用例参考:https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
4:是否返回布尔值,请根据自己的实践和要求进行选择。
最后,我希望这可以帮助任何面临此问题的人,因为 AWS S3 文档中没有现成的示例。
【讨论】:
【参考方案2】:不确定您为什么不想使用 SDK(这就是它的用途),但即使您不想使用整个 AWSSDK,您仍然可以使用其中的一部分 - 或者至少看看如何他们在幕后做这件事。
这里全部开源:
https://github.com/aws/aws-sdk-net/tree/master/AWSSDK_DotNet45/Amazon.S3
最终,您正在寻找的答案就在其中 - 但它可能比将其取出来的工作更多。
【讨论】:
啊,没想到要看看,谢谢!我将浏览它,看看它是否值得。我的程序中有另一个 API 处理程序发出 HTTP 请求,我计划使用单独的 API 处理程序来组装请求,然后使用单个 HttpHandler 类来实际发出请求。这就是我对使用原生 .NET 工具感兴趣的原因。 链接现在是 404,我假设这是新的 URL:github.com/aws/aws-sdk-net 不想使用 Amazon SDK 的一个很好的理由是通过下载几兆字节大的 .DLL(例如 AWSDK.S3 超过 2MB)来避免使原本纤细的项目变得臃肿。例如客户端 Blazor 站点。以上是关于如何在不使用 SDK 的情况下使用 .NET HttpClient 上传到 Amazon S3的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 Android SDK 的 playUri 的情况下获取歌曲元数据?
如何在不刷新页面的情况下使用 JS SDK 检测从 fb 注销
如何在不使用 SDK 的情况下将文件从 Android 上传到 Amazon S3
如何在不暴露源代码的情况下将 SDK 分发为 AAR 文件?