Net Core 發送 AWS Presigned URL 卻一直無法發送

Net Core AWS Presigned URL  無法成功發送

最近在發送AWS PresignedURL  卻一直收到 SignatureDoesNotMatch,但是我明明使用 Postman卻可以正常發送,而且還複製他那邊產生的程式碼來進行發送都是失敗

其實一直存在的原因都是  要給 streamContent   的Header  賦予 ContentType,讓它知道你要傳的確實是你說的檔案格式

using var streamContent = new StreamContent(
new FileStream(filePath, FileMode.Open, FileAccess.Read));
var client = _httpClientFactory.CreateClient();
streamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/csv");
var response = await client.PutAsync(presignedUrl, streamContent);

重點就是在 streamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/csv");

如果缺少了這段,怎麼嘗試都不會成功


但因為我現在都使用了 Refit  當我的 HttpClient  發送 API

但總是發送時候也會得到 AWS Presigned  的回應 AccessDenied,完全不知道在錯誤什麼?

研究了很久

總算研究出第一版

 

Demo.cs

public async void DemoAsync(string presignedUrl,StreamContent streamContent)
{
	var settings = new RefitSettings
	{
		HttpMessageHandlerFactory = () => new UploadPresignedURLDelegatingHandler(presignedUrl, streamContent)
	};
	var api = RestService.For<IAWSPresignedUrlRefitApi>(presignedUrl, settings);
	var apiResponse = await api.UploadPresignedUrlAsync();
}

由於無法事先使用DI注入RefitSettings,所以只要建立好Refit的介面即可

然後大家會想到為什麼要塞入兩邊presignedUrl因為只有放到 Handler會有效,否則會被AWS發送出 403錯誤

RestService.For  這邊純粹只是因為他沒有一個專屬給RefitSettings使用的function,而且給空值也會錯誤所以就直接重複給沒關係反正最後會被 DelegatingHandler  處理掉

UploadPresignedURLDelegatingHandler.cs

    public class UploadPresignedURLDelegatingHandler: DelegatingHandler
    {
        private readonly string _presignUrl;
        private readonly StreamContent _streamContent;

        public UploadPresignedURLDelegatingHandler(string presignUrl,StreamContent streamContent, , HttpMessageHandler? innerHandler = null):base(innerHandler ?? new HttpClientHandler())
        {
            _presignUrl = presignUrl;
            _streamContent = streamContent;
        }
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            request.Method = HttpMethod.Put;
            request.RequestUri = new Uri(_presignUrl);
            request.Content = _streamContent;
            return base.SendAsync(request, cancellationToken);
        }
    }

IAWSPresignedUrlRefitApi.cs

    public interface IAWSPresignedUrlRefitApi
    {
        [Put("")]
        Task<HttpResponseMessage> UploadPresignedUrlAsync();
    }

而StreamContent的作法跟前面類似

var filePath = @"D:\Demo\Demo.csv"
using var streamContent = new StreamContent(
new FileStream(filePath, FileMode.Open, FileAccess.Read));
streamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/csv");

這樣就完結哩