I'm POSTing a file to a WCF REST service through a HTML form, with enctype
set to multipart/form-data
and a single component: <input type="file" name="data">
. The resulting stream being read by the server contains the following:
------WebKitFormBoundary Content-Disposition: form-data; name="data"; filename="DSCF0001.JPG" Content-Type: image/jpeg <file bytes> ------WebKitFormBoundary--
The problem is that I'm not sure how do extract the file bytes from the stream. I need to do this in order to write the file to the disk.
Follow this rules when creating a multipart form: Specify enctype="multipart/form-data" attribute on a form tag. Add a name attribute to a single input type="file" tag. DO NOT add a name attribute to any other input, select or textarea tags.
With curl, you add each separate multipart with one -F (or --form ) flag and you then continue and add one -F for every input field in the form that you want to send.
Multipart upload allows you to upload a single object as a set of parts. Each part is a contiguous portion of the object's data. You can upload these object parts independently and in any order. If transmission of any part fails, you can retransmit that part without affecting other parts.
Sorry for joining the party late, but there is a way to do this with Microsoft public API.
Here's what you need:
System.Net.Http.dll
System.Net.Http.Formatting.dll
Note The Nuget packages come with more assemblies, but at the time of writing you only need the above.
Once you have the assemblies referenced, the code can look like this (using .NET 4.5 for convenience):
public static async Task ParseFiles( Stream data, string contentType, Action<string, Stream> fileProcessor) { var streamContent = new StreamContent(data); streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); var provider = await streamContent.ReadAsMultipartAsync(); foreach (var httpContent in provider.Contents) { var fileName = httpContent.Headers.ContentDisposition.FileName; if (string.IsNullOrWhiteSpace(fileName)) { continue; } using (Stream fileContents = await httpContent.ReadAsStreamAsync()) { fileProcessor(fileName, fileContents); } } }
As for usage, say you have the following WCF REST method:
[OperationContract] [WebInvoke(Method = WebRequestMethods.Http.Post, UriTemplate = "/Upload")] void Upload(Stream data);
You could implement it like so
public void Upload(Stream data) { MultipartParser.ParseFiles( data, WebOperationContext.Current.IncomingRequest.ContentType, MyProcessMethod); }
You may take a look at the following blog post which illustrates a technique that could be used to parse multipart/form-data
on the server using the Multipart Parser:
public void Upload(Stream stream) { MultipartParser parser = new MultipartParser(stream); if (parser.Success) { // Save the file SaveFile(parser.Filename, parser.ContentType, parser.FileContents); } }
Another possibility is to enable aspnet compatibility and use HttpContext.Current.Request
but that's not a very WCFish way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With