Read multipart/mixed in C# (.NET 4.0)

Theodore K. picture Theodore K. · Jul 18, 2014 · Viewed 10.2k times · Source

I get a multipart/mixed (with a JSON object and a file) like this, as response when I call a web service:

"--Boundary_9_15033478_1405613164044\r\n

Content-Type: application/json
\r\n\r\n{\"docId\":9007492,\"protId\":200,\"protNum\":\"0002084B14\",\"protDate\":\"Wed Jul 16 00:00:00 EEST 2014\",\"categoryId\":1000,\"desc\":\"ѥ񩣱ⷞ ��ƣ䲜��",\"linkNum\":\"ư1\\/00005545\",\"flag1\":\"\",\"flag2\":\"\",\"flag3\":\"\",\"flag4\":\"\",\"stsId\":1,\"stsDesc\":\"WS04: Check Layer I - OK\",\"wsDataList\":[],\"fileName\":\"WsTestToolkitMain.jpg\"}\r\n--Boundary_9_15033478_1405613164044\r\n

Content-Type: application/octet-stream
\r\n\r\n????\0JFIF\0\0`\0`\0\0??\0C\0\a\a\a\a\a\a\b\t\v\t\b\b\n\b\a\a\n\r\n\n\v\f\f\f
...
...
...
??\n?$??\0???????\r\n--Boundary_9_15033478_1405613164044--\r\n"

The way I got it is by getting a Stream of the response (of the HttpWebRequest) and then decode it with UTF-8. This gives me the above String. The question is how can I get the JSON and (more importantly) save the file ?

I tried changing (because they are for multipart/form-data not multipart/mixed) this and this but I can't get the file, maybe because its Content-Type is application/octet-stream . Here is what doesn't work, file appears as it was damaged/corrupted in windows:

// Read the stream into a byte array
byte[] data = ToByteArray(stream);//Source
string content = encoding.GetString(data);
int contentLength = content.Length;//Length
byte[] fileData = new byte[contentLength];//Destination
Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
this.FileContents = fileData;
File.WriteAllBytes("G:\\" + parser.Filename, parser.FileContents);

UPDATE: Followed the answer by Anton Tykhyy (thanks!) but I'm getting an error when

var multipart = await content.ReadAsMultipartAsync () ;

Invalid 'HttpContent' instance provided. It does not have a content-type header value. 'HttpContent' instances must have a content-type header starting with 'multipart/'.

I tried to add this line before

content.Headers.Add("Content-Type", "multipart/mixed");

but now I'm getting another error (that I don't really understand too)

Invalid 'HttpContent' instance provided. It does not have a 'multipart' content-type header with a 'boundary' parameter.

UPDATE 2: Found it, I just had to do this:

    var content = new StreamContent(httpResponse.GetResponseStream());
    content.Headers.Add("Content-Type", httpResponse.ContentType);

Answer

Anton Tykhyy picture Anton Tykhyy · Sep 16, 2014

Use ReadAsMultipartAsync in the System.Net.Http.Formatting assembly, along the lines of

var content   = new StreamContent (stream) ;
var multipart = await content.ReadAsMultipartAsync () ;
foreach (var part in multipart)
{
    if (part.Headers.ContentType.MediaType == "application/json")
    {
        // deserialize via stream e.g. part.ReadAsStreamAsync () or via string
        // using part.ReadAsStringAsync () to avoid charset grief
    }
    else
    using (var file = File.Create (parser.Filename))
        await part.CopyToAsync (file) ;
}

This ought to get you started.