Skip to content

Instantly share code, notes, and snippets.

@cakriwut
Created December 29, 2015 14:58
Show Gist options
  • Save cakriwut/fab729cad785047cc8f0 to your computer and use it in GitHub Desktop.
Save cakriwut/fab729cad785047cc8f0 to your computer and use it in GitHub Desktop.
ServiceStack Extensions to POST multiple files along with dto.
///<summary>
/// ServiceClient Base Extensions
/// Author: Riwut Libinuko
/// Created Date: 29/12/2015
/// Website : http://blog.libinuko.com
/// Copyright(c) 2015
/// Use PostFilesWithRequest<TResponse>(...) , to POST metadata and multiple files attachment in single request
///</summary>
public static class ServiceClientBaseExtensions
{
public static void Write(this Stream stream, string text)
{
var bytes = Encoding.UTF8.GetBytes(text);
stream.Write(bytes, 0, bytes.Length);
}
internal static void AddBasicAuth(this WebRequest client, string userName, string password)
{
client.Headers[ServiceStack.Common.Web.HttpHeaders.Authorization]
= "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(userName + ":" + password));
}
internal static TResponse HandleResponse<TResponse>(ServiceClientBase service, WebResponse webResponse)
{
if (typeof(TResponse) == typeof(HttpWebResponse) && (webResponse is HttpWebResponse))
{
return (TResponse)Convert.ChangeType(webResponse, typeof(TResponse));
}
if (typeof(TResponse) == typeof(Stream)) //Callee Needs to dispose manually
{
return (TResponse)(object)webResponse.GetResponseStream();
}
using (var responseStream = webResponse.GetResponseStream())
{
if (typeof(TResponse) == typeof(string))
{
using (var reader = new StreamReader(responseStream))
{
return (TResponse)(object)reader.ReadToEnd();
}
}
if (typeof(TResponse) == typeof(byte[]))
{
return (TResponse)(object)responseStream.ReadFully();
}
var response = service.DeserializeFromStream<TResponse>(responseStream);
return response;
}
}
public static TResponse PostFilesWithRequest<TResponse>(this ServiceClientBase sender, string relativeOrAbsoluteUrl, ICredentials creds, object request, params FileStreamInfo[] files)
{
var requestUri = sender.GetUrl(relativeOrAbsoluteUrl);
Action<Stream, FileStreamInfo, string, string> writeFileStream = null;
writeFileStream = (outputStream, inputFileInfo, boundary, newLine) =>
{
var currentStreamPosition = inputFileInfo.InputStream.Seek(0,SeekOrigin.Begin);
var header = String.Format("{0}{1}Content-Disposition: form-data; name=\"{2}\"; filename=\"{3}\"{1}{1}", boundary, newLine, "upload", inputFileInfo.Filename);
outputStream.Write(header);
var buffer = new byte[4096];
int byteCount;
while ((byteCount = inputFileInfo.InputStream.Read(buffer, 0, 4096)) > 0)
{
outputStream.Write(buffer, 0, byteCount);
}
outputStream.Write(newLine);
};
//var p = new MultipartFormDataContent(boundary);
//p.Add()
Func<WebRequest> createWebRequest = () =>
{
// PrepareWebRequest
var webRequest = (HttpWebRequest)WebRequest.Create(requestUri);
try
{
webRequest.Accept = sender.Accept;
webRequest.Method = HttpMethods.Post;
webRequest.Headers.Add(sender.Headers);
if (sender.Proxy != null) webRequest.Proxy = sender.Proxy;
if (sender.Timeout.HasValue) webRequest.Timeout = (int)sender.Timeout.Value.TotalMilliseconds;
if (sender.ReadWriteTimeout.HasValue) webRequest.ReadWriteTimeout = (int)sender.ReadWriteTimeout.Value.TotalMilliseconds;
if (creds != null) webRequest.Credentials = creds;
// if(null != sender.) client.AddAuthInfo(username,password,authInfo);
if (sender.AlwaysSendBasicAuthHeader) webRequest.AddBasicAuth(sender.UserName, sender.Password);
if (!sender.DisableAutoCompression)
{
webRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
webRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}
if (sender.StoreCookies)
{
webRequest.CookieContainer = sender.CookieContainer;
}
webRequest.AllowAutoRedirect = sender.AllowAutoRedirect;
// ignore requestwebfilter
webRequest.ContentType = sender.ContentType;
}
catch (Exception ex)
{
throw new Exception("PortFilesWithRequest", ex);
}
var queryString = QueryStringSerializer.SerializeToString(request);
var nameValueCollection = HttpUtility.ParseQueryString(queryString);
var boundary = DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture);
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
boundary = "--" + boundary;
var newLine = "\r\n";
using (var outputStream = webRequest.GetRequestStream())
{
foreach (var key in nameValueCollection.AllKeys)
{
outputStream.Write(boundary + newLine);
outputStream.Write("Content-Disposition: form-data;name=\"{0}\"{1}".FormatWith(key, newLine));
outputStream.Write("Content-Type: text/plain;charset=utf-8{0}{1}".FormatWith(newLine, newLine));
outputStream.Write(nameValueCollection[key] + newLine);
}
foreach (var file in files)
{
writeFileStream(outputStream, file, boundary, newLine);
}
outputStream.Write(boundary + "--"); // Finalize boundary
}
return webRequest;
};
// The execution
try
{
var webRequest = createWebRequest();
var webResponse = webRequest.GetResponse();
if (webResponse is HttpWebResponse)
{
if (ServiceClientBase.HttpWebResponseFilter != null)
ServiceClientBase.HttpWebResponseFilter((HttpWebResponse)webResponse);
if (sender.LocalHttpWebResponseFilter != null)
sender.LocalHttpWebResponseFilter((HttpWebResponse)webResponse);
}
return HandleResponse<TResponse>(sender, webResponse);
}
catch (Exception ex)
{
throw new Exception("Can not PostFilesWithRequest", ex);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment