首页 > 解决方案 > 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-web-servicesamazon-s3c#-4.0restsharp

解决方案


使用 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


推荐阅读