I need to upload files from client machine to a remote server and for that i have created a windows application which will work as client. It will select the required file and call the Web API.
Please find my client code as below :
//...other code removed for brevity private void UploadFile(string filename) { Stream ms = new MemoryStream(); using (FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read)) { var fileInfo = new FileInfo(filename); byte[] bytes = new byte[file.Length]; file.Read(bytes, 0, (int)file.Length); ms.Write(bytes, 0, (int)file.Length); MultiPartFormUpload multiPartFormUpload = new MultiPartFormUpload(); List<FileInfo> files = new List<FileInfo>() { fileInfo }; try { MultiPartFormUpload.UploadResponse response = multiPartFormUpload.Upload("http://localhost:10458/api/Upload", files); } catch (Exception ex) { throw ex; } } } public class MultiPartFormUpload { public class MimePart { NameValueCollection _headers = new NameValueCollection(); byte[] _header; public NameValueCollection Headers { get { return _headers; } } public byte[] Header { get { return _header; } } public long GenerateHeaderFooterData(string boundary) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("--"); stringBuilder.Append(boundary); stringBuilder.AppendLine(); foreach (string key in _headers.AllKeys) { stringBuilder.Append(key); stringBuilder.Append(": "); stringBuilder.AppendLine(_headers[key]); } stringBuilder.AppendLine(); _header = Encoding.UTF8.GetBytes(stringBuilder.ToString()); return _header.Length + Data.Length + 2; } public Stream Data { get; set; } } public class UploadResponse { public UploadResponse(HttpStatusCode httpStatusCode, string responseBody) { HttpStatusCode = httpStatusCode; ResponseBody = responseBody; } public HttpStatusCode HttpStatusCode { get; set; } public string ResponseBody { get; set; } } public UploadResponse Upload(string url, List<FileInfo> files) { using (WebClient client = new WebClient()) { List<MimePart> mimeParts = new List<MimePart>(); try { foreach (FileInfo file in files) { MimePart part = new MimePart(); string name = file.Extension.Substring(1); string fileName = file.Name; part.Headers["Content-Disposition"] = "form-data; name=\"" + name + "\"; filename=\"" + fileName + "\""; part.Headers["Content-Type"] = "application/octet-stream"; part.Data = new MemoryStream(File.ReadAllBytes(file.FullName)); mimeParts.Add(part); } string boundary = "----------" + DateTime.Now.Ticks.ToString("x"); client.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + boundary); long contentLength = 0; byte[] _footer = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n"); foreach (MimePart mimePart in mimeParts) { contentLength += mimePart.GenerateHeaderFooterData(boundary); } byte[] buffer = new byte[8192]; byte[] afterFile = Encoding.UTF8.GetBytes("\r\n"); int read; using (MemoryStream memoryStream = new MemoryStream()) { foreach (MimePart mimePart in mimeParts) { memoryStream.Write(mimePart.Header, 0, mimePart.Header.Length); while ((read = mimePart.Data.Read(buffer, 0, buffer.Length)) > 0) memoryStream.Write(buffer, 0, read); mimePart.Data.Dispose(); memoryStream.Write(afterFile, 0, afterFile.Length); } memoryStream.Write(_footer, 0, _footer.Length); byte[] responseBytes = client.UploadData(url, memoryStream.ToArray()); string responseString = Encoding.UTF8.GetString(responseBytes); return new UploadResponse(HttpStatusCode.OK, responseString); } } catch (Exception ex) { foreach (MimePart part in mimeParts) if (part.Data != null) part.Data.Dispose(); if (ex.GetType().Name == "WebException") { WebException webException = (WebException)ex; HttpWebResponse response = (HttpWebResponse)webException.Response; string responseString; using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { responseString = reader.ReadToEnd(); } return new UploadResponse(response.StatusCode, responseString); } else { throw; } } } } }
Please find Web API code as below :
public async Task<HttpResponseMessage> Post() { if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } string fileSaveLocation = HttpContext.Current.Server.MapPath("~/upload/files"); CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(fileSaveLocation); List<string> files = new List<string>(); try { await Request.Content.ReadAsMultipartAsync(provider); foreach (MultipartFileData file in provider.FileData) { files.Add(Path.GetFileName(file.LocalFileName)); } // Send OK Response along with saved file names to the client. return Request.CreateResponse(HttpStatusCode.OK, files); } catch (System.Exception e) { return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e); } } public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider { public CustomMultipartFormDataStreamProvider(string path) : base(path) { } public override string GetLocalFileName(HttpContentHeaders headers) { return headers.ContentDisposition.FileName.Replace("\"", string.Empty); } }
I am able to hit the Web API with the client code but fileInfo.Length is coming 0.
Please let me know what i am missing in Client or Web API code. Thanks !