amazon-web-services - HttpClient C# PutAsync 到 S3 存储桶与提供的签名不匹配
问题描述
我正在尝试通过上传 URL 将图像放在 s3 存储桶上。这是我到目前为止所做的:
//Get Upload URL & Access the file details
string path = HttpUtility.UrlPathEncode("image/getUploadURL/" + imageFileDetails.Extension + "/" + imageFileDetails.Name + "/" + sessionID);
string uploadURL = " ";
string mimeType = MimeTypesMap.GetMimeType(imageFileDetails.FullName);
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
var getResponse = await response.Content.ReadAsStringAsync();
dynamic JSONObject = JObject.Parse(getResponse);
uploadURL = JSONObject.data.uploadURL;
if (uploadURL != "" && uploadURL != null)
{
using (var content = new MultipartFormDataContent())
{
Console.WriteLine("UploadURL: {0}", uploadURL);
Console.WriteLine("newFilePath: {0}", newFilePath);
FileStream fileStream = new FileStream(newFilePath, FileMode.Open);
content.Add(new StreamContent(fileStream), "data");
using (
var message = await client.PutAsync(uploadURL, content))
{
var putResponse = await message.Content.ReadAsStringAsync();
Console.WriteLine("PutResponse: {0} " , putResponse);
}
}
Console.ReadKey();
}
我继续收到以下错误:
我们计算的请求签名与您提供的签名不匹配。检查您的密钥和签名方法。
我应该以不同的方式处理这个问题吗?我也尝试过 RestSharp,但还没有得到任何积极的结果。任何想法或解决方法将不胜感激!
解决方案
使用 Amazon S3 强类型 C# 客户端。要使用预签名 URL 上传对象,您可以使用此代码。
namespace UploadUsingPresignedURLExample
{
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Amazon.S3;
using Amazon.S3.Model;
/// <summary>
/// This example shows how to upload an object to an Amazon Simple Storage
/// Service (Amazon S3) bucket using a presigned URL. The code first
/// creates a presigned URL and then uses it to upload an object to an
/// Amazon S3 bucket using that URL. The example was created using the
/// AWS SDK for .NET version 3.7 and .NET Core 5.0.
/// </summary>
public class UploadUsingPresignedURL
{
public static void Main()
{
string bucketName = "doc-example-bucket";
string keyName = "samplefile.txt";
string filePath = $"source\\{keyName}";
// Specify how long the signed URL will be valid in hours.
double timeoutDuration = 12;
// If the AWS Region defined for your default user is different
// from the Region where your Amazon S3 bucket is located,
// pass the Region name to the S3 client object's constructor.
// For example: RegionEndpoint.USWest2.
IAmazonS3 client = new AmazonS3Client();
var url = GeneratePreSignedURL(client, bucketName, keyName, timeoutDuration);
var success = UploadObject(filePath, url);
if (success)
{
Console.WriteLine("Upload succeeded.");
}
else
{
Console.WriteLine("Upload failed.");
}
}
/// <summary>
/// Uploads an object to an S3 bucket using the presigned URL passed in
/// the url parameter.
/// </summary>
/// <param name="filePath">The path (including file name) to the local
/// file you want to upload.</param>
/// <param name="url">The presigned URL that will be used to upload the
/// file to the S3 bucket.</param>
/// <returns>A Boolean value indicating the success or failure of the
/// operation, based on the HttpWebResponse.</returns>
public static bool UploadObject(string filePath, string url)
{
HttpWebRequest httpRequest = WebRequest.Create(url) as HttpWebRequest;
httpRequest.Method = "PUT";
using (Stream dataStream = httpRequest.GetRequestStream())
{
var buffer = new byte[8000];
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
dataStream.Write(buffer, 0, bytesRead);
}
}
}
HttpWebResponse response = httpRequest.GetResponse() as HttpWebResponse;
return response.StatusCode == HttpStatusCode.OK;
}
/// <summary>
/// Generates a presigned URL which will be used to upload an object to
/// an S3 bucket.
/// </summary>
/// <param name="client">The initialized S3 client object used to call
/// GetPreSignedURL.</param>
/// <param name="bucketName">The name of the S3 bucket to which the
/// presigned URL will point.</param>
/// <param name="objectKey">The name of the file that will be uploaded.</param>
/// <param name="duration">How long (in hours) the presigned URL will
/// be valid.</param>
/// <returns>The generated URL.</returns>
public static string GeneratePreSignedURL(
IAmazonS3 client,
string bucketName,
string objectKey,
double duration)
{
var request = new GetPreSignedUrlRequest
{
BucketName = bucketName,
Key = objectKey,
Verb = HttpVerb.PUT,
Expires = DateTime.UtcNow.AddHours(duration),
};
string url = client.GetPreSignedURL(request);
return url;
}
}
}
您可以在 Github 中找到此示例和其他 Amazon S3 示例:
https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/dotnetv3/S3
推荐阅读
- java - 如何将搜索过滤器面板连接到 ArrayList
并在 ExpandableListView 中显示结果? - python - Python3 ImportError:尝试在没有已知父包的情况下进行相对导入
- python - 如何在通过 MS DevOps 运行管道时在自托管(Linux Ubuntu 18.04)代理上指定 python 版本
- flutter - Flutter ListWheelScrollView , 如何添加水平线
- bluetooth - Ble 外围断开处理程序在 gattlib c 库中不起作用
- python - 列表作为每个列表中具有多个值的字典的值
- laravel - Vuejs 在 laravel 的视图中效果不佳
- python - 如何在 Vs 代码中为 Python 使用 emmet
- excel - 为什么在粘贴变体值时我会检索数字 intead 文本?
- php - 公用文件夹移出根目录的 Laravel 停止工作