/// <summary> /// Upload an array of files to a remote host using the HTTP post or put multipart method /// </summary> /// <param name="url">Target url</param> /// <param name="method">Request Method - POST or PUT</param> /// <param name="parameters">Parmaters</param> /// <param name="files">An array of files</param> /// <param name="successCallback">Funciton that is called on success</param> /// <param name="failCallback">Function that is called on failure</param> public static void Upload(string url, HttpLibVerb method, object parameters, HttpLibFileStream[] files, Action<WebHeaderCollection, Stream> successCallback, Action<WebException> failCallback) { if (method != HttpLibVerb.Post && method != HttpLibVerb.Put) { throw new ArgumentException("Request method must be POST or PUT"); } try { /* * Generate a random boundry string */ string boundary = RandomString(12); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url)); request.Method = method.ToString(); request.ContentType = "multipart/form-data, boundary=" + boundary; request.CookieContainer = cookies; request.BeginGetRequestStream(new AsyncCallback((IAsyncResult asynchronousResult) => { /* * Create a new request */ HttpWebRequest tmprequest = (HttpWebRequest)asynchronousResult.AsyncState; /* * Get a stream that we can write to */ Stream postStream = tmprequest.EndGetRequestStream(asynchronousResult); string querystring = "\n"; /* * Serialize parameters in multipart manner */ #if NETFX_CORE foreach (var property in parameters.GetType().GetTypeInfo().DeclaredProperties) #else foreach (var property in parameters.GetType().GetProperties()) #endif { querystring += "--" + boundary + "\n"; querystring += "content-disposition: form-data; name=\"" + System.Uri.EscapeDataString(property.Name) + "\"\n\n"; querystring += System.Uri.EscapeDataString(property.GetValue(parameters, null).ToString()); querystring += "\n"; } /* * Then write query string to the postStream */ byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(querystring); postStream.Write(byteArray, 0, byteArray.Length); /* * A boundary string that we'll reuse to separate files */ byte[] closing = System.Text.Encoding.UTF8.GetBytes("\n--" + boundary + "--\n"); /* * Write each files to the postStream */ foreach (HttpLibFileStream file in files) { /* * A temporary buffer to hold the file stream * Not sure if this is needed ??? */ Stream outBuffer = new MemoryStream(); /* * Additional info that is prepended to the file */ string qsAppend; qsAppend = "--" + boundary + "\ncontent-disposition: form-data; name=\"" + file.Name + "\"; filename=\"" + file.Filename + "\"\r\nContent-Type: " + file.ContentType + "\r\n\r\n"; /* * Read the file into the output buffer */ StreamReader sr = new StreamReader(file.Stream); outBuffer.Write(System.Text.Encoding.UTF8.GetBytes(qsAppend), 0, qsAppend.Length); int bytesRead = 0; byte[] buffer = new byte[4096]; while ((bytesRead = file.Stream.Read(buffer, 0, buffer.Length)) != 0) { outBuffer.Write(buffer, 0, bytesRead); } /* * Write the delimiter to the output buffer */ outBuffer.Write(closing, 0, closing.Length); /* * Write the output buffer to the post stream using an intemediate byteArray */ outBuffer.Position = 0; byte[] tempBuffer = new byte[outBuffer.Length]; outBuffer.Read(tempBuffer, 0, tempBuffer.Length); postStream.Write(tempBuffer, 0, tempBuffer.Length); postStream.Flush(); } postStream.Flush(); postStream.Dispose(); tmprequest.BeginGetResponse(ProcessCallback(successCallback, failCallback), tmprequest); }), request); } catch (WebException webEx) { failCallback(webEx); } }
private static void MakeRequest(string contentType, HttpLibVerb method, string url, object parameters, Action<WebHeaderCollection, Stream> successCallback, Action<WebException> failCallback) { if (parameters == null) { throw new ArgumentNullException("parameters object cannot be null"); } if (string.IsNullOrWhiteSpace(url)) { throw new ArgumentException("url is empty"); } try { /* * Create new Request */ HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url)); request.CookieContainer = cookies; request.Method = method.ToString(); /* * Asynchronously get the response */ if (method == HttpLibVerb.Delete || method == HttpLibVerb.Post || method == HttpLibVerb.Put || method == HttpLibVerb.Patch) { request.ContentType = contentType; request.BeginGetRequestStream(new AsyncCallback((IAsyncResult callbackResult) => { HttpWebRequest tmprequest = (HttpWebRequest)callbackResult.AsyncState; Stream postStream; postStream = tmprequest.EndGetRequestStream(callbackResult); string postbody = ""; postbody = parameters.ToQueryString(); // Convert the string into a byte array. byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(postbody); // Write to the request stream. postStream.Write(byteArray, 0, byteArray.Length); postStream.Flush(); postStream.Dispose(); // Start the asynchronous operation to get the response tmprequest.BeginGetResponse(ProcessCallback(successCallback, failCallback), tmprequest); }), request); } else if (method == HttpLibVerb.Get || method == HttpLibVerb.Head) { request.BeginGetResponse(ProcessCallback(successCallback, failCallback), request); } } catch (WebException webEx) { failCallback(webEx); } }
/// <summary> /// Upload an array of files to a remote host using the HTTP post or put multipart method /// </summary> /// <param name="url">Target url</param> /// <param name="method">Request Method - POST or PUT</param> /// <param name="parameters">Parmaters</param> /// <param name="files">An array of files</param> /// <param name="successCallback">Funciton that is called on success</param> /// <param name="failCallback">Function that is called on failure</param> public static void Upload(string url, HttpLibVerb method, object parameters, HttpLibFileStream[] files, Action<string> successCallback, Action<WebException> failCallback) { Upload(url, method, parameters, files, StreamToStringCallback(successCallback), failCallback); }