我在尝试在 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 文档中没有现成的示例。