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");
這樣就完結哩