Reading multipart content from raw http request
Solution 1
You are adding a StreamContent
as a part to the empty MultipartFormDataContent
. Naturally, ReadAsMultipartAsync
then does nothing. Instead, you want to read the StreamContent
. Also, your file contains not just the content, but the headers as well. If you snip off the headers, this ought to work:
using (var stream = File.Open (@"C:\temp\test.txt", FileMode.Open))
{
// note: StreamContent has no Content-Type set by default
// set a suitable Content-Type for ReadAsMultipartAsync()
var content = new StreamContent (stream) ;
content.Headers.ContentType =
System.Net.Http.Headers.MediaTypeHeaderValue.Parse (
"multipart/related; boundary=cbsms-main-boundary") ;
// TODO: make this recursive if required...
var outerMultipart = await stream.ReadAsMultipartAsync () ;
foreach (var outerPart in outerMultipart.Contents)
{
if (outerPart.IsMimeMultipartContent())
{
var innerMultipart = await outerPart.ReadAsMultipartAsync () ;
foreach (var innerPart in innerMultipart.Contents) // do stuff
}
else // do other stuff
}
}
Solution 2
Use HttpContentMultipartExtensions class and ReadAsMultipartAsync method http://msdn.microsoft.com/en-us/library/hh835439%28v=vs.108%29.aspx
Good example is here: http://www.asp.net/web-api/overview/working-with-http/sending-html-form-data,-part-2
user517406
Updated on July 11, 2022Comments
-
user517406 almost 2 years
I am saving a raw HTTP request to a text file and I need to read the multipart content within it. I know there are a number of 3rd party tools to do this but I need to do this with the .NET framework if possible. I have tried reading the txt file into a stream but I don't know how to extract the multipart content. Here is an example of the code I have been using and a sample file I am trying to read from :
var content = new MultipartFormDataContent(); var stream = new StreamContent(File.Open(@"C:\temp\test.txt", FileMode.Open)); content.Add(stream); List<StreamContent> lstStreamContents = new List<StreamContent>(); if (content != null) { if (content.IsMimeMultipartContent()) await content.ReadAsMultipartAsync(StreamProvider); foreach (MultipartContent multiPartContent in content) { foreach (var streamContent in multiPartContent).....
Text file :
Cache-Control: no-cache Connection: Close Content-Length: 5216 Content-Type: multipart/related; boundary="cbsms-main-boundary"; start="<soap-envelope>", text/xml; charset=utf-8 Accept: */* Host: hostname User-Agent: Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5) soapaction: "" This is a multi-part message in MIME format. --cbsms-main-boundary Content-Type: text/xml; charset="utf-8" Content-ID: <soap-envelope> <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <mm7:TransactionID xmlns:mm7="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL -6-MM7-1-2">5947CCE35D5B4AEFB99DADDDF9472E67</mm7:TransactionID> </SOAP-ENV:Header> <SOAP-ENV:Body> <mm7:DeliverReq xmlns:mm7="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL -6-MM7-1-2"> <mm7:MM7Version>6.5.0</mm7:MM7Version> <mm7:MMSRelayServerID>hostname</mm7:MMSRelayServerID> <mm7:LinkedID>1-1754394156</mm7:LinkedID> <mm7:SenderAddress> <mm7:Number>46707630767</mm7:Number> </mm7:SenderAddress> <mm7:Recipients> <mm7:To> <mm7:Number>72401</mm7:Number> </mm7:To> </mm7:Recipients> <mm7:TimeStamp>2008-05-08 11:16:39</mm7:TimeStamp> <mm7:Priority>Normal</mm7:Priority> <mm7:Subject>Tube test</mm7:Subject> </mm7:DeliverReq> </SOAP-ENV:Body> </SOAP-ENV:Envelope> --cbsms-main-boundary Content-Type: multipart/mixed; boundary="cbsms-sub-boundary" Content-ID: <MM7-Media> --cbsms-sub-boundary content-type: application/smil; Name=main.smil;Charset=utf-8 content-transfer-encoding: 7bit content-id: <AAAA> content-length: 483 <smil><head><layout><root-layout backgroundColor="#FFFFFF" background-color="#FFFFFF" height="480px" width="640px"/> <region id="Image" top="0" left="0" height="50%" width="100%" fit="meet"/> <region id="Text" top="50%" left="0" height="50%" width="100%" fit="scroll"/> </layout> </head> <body><par dur="4000ms"><img src="smslogo.jpg" region="Image"></img> <text src="smil.txt" region="Text"><param name="foreground-color" value="#000000"/> </text> </par> </body> </smil> --cbsms-sub-boundary content-type: image/jpeg; Name=smslogo.jpg content-transfer-encoding: Base64 content-location: smslogo.jpg content-length: 2218 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 OD//2Q== --cbsms-sub-boundary content-type: text/plain; Name=smil.txt;Charset=utf-8 content-transfer-encoding: 7bit content-location: smil.txt content-length: 9 Tube test --cbsms-sub-boundary-- --cbsms-main-boundary--
At the moment I am getting this error 'Unable to cast object of type 'System.Net.Http.StreamContent' to type 'System.Net.Http.MultipartContent'.'
EDIT :
foreach (var part in multipart.Contents) { if (part.Headers.ContentType.MediaType == "multipart/mixed") { if (part.IsMimeMultipartContent()) await part.ReadAsMultipartAsync(StreamProvider); foreach (MultipartContent multiPartContent in StreamProvider.Contents) {
This gives the error ''Unexpected end of MIME multipart stream. MIME multipart message is not complete'
-
user517406 over 10 yearsThanks for the answer, I think that is on the right track, however I cannot set Headers.ContentType for the stream object
-
user517406 over 10 yearsFound the issue, should be referring to content object rather than stream
-
user517406 over 10 yearsExcellent...that gets me 2 content types, "text-xml" and "multipart/mixed"...that enables me to parse the xml, but how would I get the content type "image/jpeg" from within the "multipart/mixed" content?
-
Anton Tykhyy over 10 yearsUm... you just get it? By, you know, looping over
multipart.Contents
? -
user517406 over 10 yearsLooping through multipart.Contents gives me 2 parts, text-xml and multipart-mixed. The question I was asking was how do I get the image from the multipart-mixed part. I am not sure how to iterate through the multipart-mixed part to get at image-jpeg. Please see Edit above which explains this
-
user517406 over 10 yearsFigured it out, I needed to set the stream position back to 0
-
Anton Tykhyy over 10 yearsI missed that you had nested multipart contents. You iterate through the inner mixed content the same way as through the outer mixed content, except the headers are parsed for you. Your edit is wrong because again you are not reading the inner multi-part content. See my edit here. You must use the return value of
ReadAsMultipartAsync
! -
Jesse Chisholm almost 6 yearsOddly enough,
new MediaTypeHeaderValue("multipart/related; boundary=cbsms-main-boundary")
didn't do exactly the same things asMediaTypeHeaderValue.Parse("multipart/related; boundary=cbsms-main-boundary")
Apparently the constructor only wants the subtype, the the other attributes. Whereas Parse knows what to do with the other attributes.