From 1e1e0ad9c66162efd558386d897634ce318ebf84 Mon Sep 17 00:00:00 2001 From: Demis Bellot Date: Tue, 27 Oct 2020 13:01:22 +0800 Subject: [PATCH] Extract .NET 4.5 HttpUtils + add async overloads --- src/ServiceStack.Text/HttpUtils.cs | 170 ++++++++++++++++++++++- src/ServiceStack.Text/PclExport.Net45.cs | 55 -------- 2 files changed, 166 insertions(+), 59 deletions(-) diff --git a/src/ServiceStack.Text/HttpUtils.cs b/src/ServiceStack.Text/HttpUtils.cs index a41be6dda..b58a68195 100644 --- a/src/ServiceStack.Text/HttpUtils.cs +++ b/src/ServiceStack.Text/HttpUtils.cs @@ -1076,6 +1076,15 @@ public static Task GetResponseAsync(this HttpWebRequest request return tcs.Task; } + private static byte[] GetHeaderBytes(string fileName, string mimeType, string field, string boundary) + { + var header = "\r\n--" + boundary + + $"\r\nContent-Disposition: form-data; name=\"{field}\"; filename=\"{fileName}\"\r\nContent-Type: {mimeType}\r\n\r\n"; + + var headerBytes = header.ToAsciiBytes(); + return headerBytes; + } + public static void UploadFile(this WebRequest webRequest, Stream fileStream, string fileName, string mimeType, string accept = null, Action requestFilter = null, string method = "POST", string field = "file") { @@ -1093,10 +1102,7 @@ public static void UploadFile(this WebRequest webRequest, Stream fileStream, str var boundaryBytes = ("\r\n--" + boundary + "--\r\n").ToAsciiBytes(); - var header = "\r\n--" + boundary + - $"\r\nContent-Disposition: form-data; name=\"{field}\"; filename=\"{fileName}\"\r\nContent-Type: {mimeType}\r\n\r\n"; - - var headerBytes = header.ToAsciiBytes(); + var headerBytes = GetHeaderBytes(fileName, mimeType, field, boundary); var contentLength = fileStream.Length + headerBytes.Length + boundaryBytes.Length; PclExport.Instance.InitHttpWebRequest(httpReq, @@ -1115,6 +1121,43 @@ public static void UploadFile(this WebRequest webRequest, Stream fileStream, str PclExport.Instance.CloseStream(outputStream); } + public static async Task UploadFileAsync(this WebRequest webRequest, Stream fileStream, string fileName, string mimeType, + string accept = null, Action requestFilter = null, string method = "POST", string field = "file", + CancellationToken token=default) + { + var httpReq = (HttpWebRequest)webRequest; + httpReq.Method = method; + + if (accept != null) + httpReq.Accept = accept; + + requestFilter?.Invoke(httpReq); + + var boundary = Guid.NewGuid().ToString("N"); + + httpReq.ContentType = "multipart/form-data; boundary=\"" + boundary + "\""; + + var boundaryBytes = ("\r\n--" + boundary + "--\r\n").ToAsciiBytes(); + + var headerBytes = GetHeaderBytes(fileName, mimeType, field, boundary); + + var contentLength = fileStream.Length + headerBytes.Length + boundaryBytes.Length; + PclExport.Instance.InitHttpWebRequest(httpReq, + contentLength: contentLength, allowAutoRedirect: false, keepAlive: false); + + if (ResultsFilter != null) + { + ResultsFilter.UploadStream(httpReq, fileStream, fileName); + return; + } + + using var outputStream = PclExport.Instance.GetRequestStream(httpReq); + await outputStream.WriteAsync(headerBytes, 0, headerBytes.Length, token).ConfigAwait(); + await fileStream.CopyToAsync(outputStream, 4096, token).ConfigAwait(); + await outputStream.WriteAsync(boundaryBytes, 0, boundaryBytes.Length, token).ConfigAwait(); + PclExport.Instance.CloseStream(outputStream); + } + public static void UploadFile(this WebRequest webRequest, Stream fileStream, string fileName) { if (fileName == null) @@ -1126,6 +1169,17 @@ public static void UploadFile(this WebRequest webRequest, Stream fileStream, str UploadFile(webRequest, fileStream, fileName, mimeType); } + public static async Task UploadFileAsync(this WebRequest webRequest, Stream fileStream, string fileName, CancellationToken token=default) + { + if (fileName == null) + throw new ArgumentNullException(nameof(fileName)); + var mimeType = MimeTypes.GetMimeType(fileName); + if (mimeType == null) + throw new ArgumentException("Mime-type not found for file: " + fileName); + + await UploadFileAsync(webRequest, fileStream, fileName, mimeType, token: token).ConfigAwait(); + } + public static string PostXmlToUrl(this string url, object data, Action requestFilter = null, Action responseFilter = null) { @@ -1153,6 +1207,114 @@ public static string PutCsvToUrl(this string url, object data, return SendStringToUrl(url, method: "PUT", requestBody: data.ToCsv(), contentType: MimeTypes.Csv, accept: MimeTypes.Csv, requestFilter: requestFilter, responseFilter: responseFilter); } + + public static WebResponse PostFileToUrl(this string url, + FileInfo uploadFileInfo, string uploadFileMimeType, + string accept = null, + Action requestFilter = null) + { + var webReq = (HttpWebRequest)WebRequest.Create(url); + using (var fileStream = uploadFileInfo.OpenRead()) + { + var fileName = uploadFileInfo.Name; + + webReq.UploadFile(fileStream, fileName, uploadFileMimeType, accept: accept, requestFilter: requestFilter, method: "POST"); + } + + if (ResultsFilter != null) + return null; + + return webReq.GetResponse(); + } + + public static async Task PostFileToUrlAsync(this string url, + FileInfo uploadFileInfo, string uploadFileMimeType, + string accept = null, + Action requestFilter = null, CancellationToken token=default) + { + var webReq = (HttpWebRequest)WebRequest.Create(url); + using (var fileStream = uploadFileInfo.OpenRead()) + { + var fileName = uploadFileInfo.Name; + + await webReq.UploadFileAsync(fileStream, fileName, uploadFileMimeType, accept: accept, requestFilter: requestFilter, method: "POST", token: token); + } + + if (ResultsFilter != null) + return null; + + return await webReq.GetResponseAsync(); + } + + public static WebResponse PutFileToUrl(this string url, + FileInfo uploadFileInfo, string uploadFileMimeType, + string accept = null, + Action requestFilter = null) + { + var webReq = (HttpWebRequest)WebRequest.Create(url); + using (var fileStream = uploadFileInfo.OpenRead()) + { + var fileName = uploadFileInfo.Name; + + webReq.UploadFile(fileStream, fileName, uploadFileMimeType, accept: accept, requestFilter: requestFilter, method: "PUT"); + } + + if (ResultsFilter != null) + return null; + + return webReq.GetResponse(); + } + + public static async Task PutFileToUrlAsync(this string url, + FileInfo uploadFileInfo, string uploadFileMimeType, + string accept = null, + Action requestFilter = null, CancellationToken token=default) + { + var webReq = (HttpWebRequest)WebRequest.Create(url); + using (var fileStream = uploadFileInfo.OpenRead()) + { + var fileName = uploadFileInfo.Name; + + await webReq.UploadFileAsync(fileStream, fileName, uploadFileMimeType, accept: accept, requestFilter: requestFilter, method: "PUT", token: token); + } + + if (ResultsFilter != null) + return null; + + return await webReq.GetResponseAsync(); + } + + public static WebResponse UploadFile(this WebRequest webRequest, + FileInfo uploadFileInfo, string uploadFileMimeType) + { + using (var fileStream = uploadFileInfo.OpenRead()) + { + var fileName = uploadFileInfo.Name; + + webRequest.UploadFile(fileStream, fileName, uploadFileMimeType); + } + + if (ResultsFilter != null) + return null; + + return webRequest.GetResponse(); + } + + public static async Task UploadFileAsync(this WebRequest webRequest, + FileInfo uploadFileInfo, string uploadFileMimeType) + { + using (var fileStream = uploadFileInfo.OpenRead()) + { + var fileName = uploadFileInfo.Name; + + await webRequest.UploadFileAsync(fileStream, fileName, uploadFileMimeType); + } + + if (ResultsFilter != null) + return null; + + return await webRequest.GetResponseAsync(); + } } //Allow Exceptions to Customize HTTP StatusCode and StatusDescription returned diff --git a/src/ServiceStack.Text/PclExport.Net45.cs b/src/ServiceStack.Text/PclExport.Net45.cs index 3a86c4830..0e1e4df48 100644 --- a/src/ServiceStack.Text/PclExport.Net45.cs +++ b/src/ServiceStack.Text/PclExport.Net45.cs @@ -535,61 +535,6 @@ public static StringCollection ToStringCollection(List items) public static class PclExportExt { - //HttpUtils - public static WebResponse PostFileToUrl(this string url, - FileInfo uploadFileInfo, string uploadFileMimeType, - string accept = null, - Action requestFilter = null) - { - var webReq = (HttpWebRequest)WebRequest.Create(url); - using (var fileStream = uploadFileInfo.OpenRead()) - { - var fileName = uploadFileInfo.Name; - - webReq.UploadFile(fileStream, fileName, uploadFileMimeType, accept: accept, requestFilter: requestFilter, method: "POST"); - } - - if (HttpUtils.ResultsFilter != null) - return null; - - return webReq.GetResponse(); - } - - public static WebResponse PutFileToUrl(this string url, - FileInfo uploadFileInfo, string uploadFileMimeType, - string accept = null, - Action requestFilter = null) - { - var webReq = (HttpWebRequest)WebRequest.Create(url); - using (var fileStream = uploadFileInfo.OpenRead()) - { - var fileName = uploadFileInfo.Name; - - webReq.UploadFile(fileStream, fileName, uploadFileMimeType, accept: accept, requestFilter: requestFilter, method: "PUT"); - } - - if (HttpUtils.ResultsFilter != null) - return null; - - return webReq.GetResponse(); - } - - public static WebResponse UploadFile(this WebRequest webRequest, - FileInfo uploadFileInfo, string uploadFileMimeType) - { - using (var fileStream = uploadFileInfo.OpenRead()) - { - var fileName = uploadFileInfo.Name; - - webRequest.UploadFile(fileStream, fileName, uploadFileMimeType); - } - - if (HttpUtils.ResultsFilter != null) - return null; - - return webRequest.GetResponse(); - } - //XmlSerializer public static void CompressToStream(TXmlDto from, Stream stream) {