我正在编写一个用于使用某些数据的Web服务。发送它的第三方正在使用多部分请求,当我在WireShark中查看请求时,它会被分块。
当我尝试通过fiddler作为标准(unchunked)请求运行完全相同的请求时,它工作正常,但是,我似乎无法读取分块请求。
我尝试了两种不同的方法。第一:
public HttpResponseMessage ImportEstimate(HttpRequestMessage request)
{
var data = request.Content.ReadAsMultipartAsync().Result;
IEnumerable<HttpContent> parts = data.Contents;
return request.CreateResponse(HttpStatusCode.OK, parts.Count());
}
这不会返回任何内容。它只是坐着,直到请求超时。
第二种方法是:
public HttpResponseMessage ImportEstimate(HttpRequestMessage request)
{
IEnumerable<HttpContent> parts = null;
Task.Factory
.StartNew(() => parts = Request.Content.ReadAsMultipartAsync().Result.Contents,
CancellationToken.None,
TaskCreationOptions.LongRunning, // guarantees separate thread
TaskScheduler.Default)
.Wait();
return request.CreateResponse(HttpStatusCode.OK, parts.Count());
}
返回错误:
Unexpected end of MIME multipart stream. MIME multipart message is not complete.
我在这里缺少什么?
已编辑:以下是WireShark的请求
POST /myservice/importestimate HTTP/1.1
Host: devapi.mydomain.com
Content-Type: multipart/related; type="application/xop+xml"; start="<start.xml>"; start-info="text/xml"; boundary="--MIME_boundary"
Transfer-Encoding: chunked
SOAPAction: "importestimate"
X-Forwarded-For: xxx.xx.xxx.xxx
Connection: close
94
----MIME_boundary
Content-Type: application/xop+xml; type="text/xml; charset=UTF-8"
Content-Transfer-Encoding: 8bit
Content-Id: <start.xml>
170
<?xml version='1.0' encoding='UTF-8' ?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xop="http://www.w3.org/2004/08/xop/include" ><soap:Body><XDOC><XNET_INFO transactionId="001P92V" ><ATTACHMENTS><ATTACHMENT><xop:Include href="cid:3203@xactware.com" /></ATTACHMENT></ATTACHMENTS></XNET_INFO></XDOC></soap:Body></soap:Envelope>
B3
----MIME_boundary
Content-Type: application/zip
Content-Transfer-Encoding: binary
Content-Disposition: attachment; filename="XDOC.ZIP"
Content-Id: <3203@x.com>
5BC
... lots of data here removed for brevity...
15
----MIME_boundary--
0
答案 0 :(得分:1)
经过大量研究,我发现了问题!
显然我的请求并没有以CRLF结束,.Net必须要求发出请求结束的信号。
我最终阅读了整个请求,添加了CRLF,并从MemoryStream创建了自己的ReadAsMultipartAsync。这似乎有效。
编辑添加代码:
private byte[] ProcessInput(HttpRequestMessage request)
{
List<HttpContent> parts = new List<HttpContent>();
byte[] result;
result = request.Content.ReadAsByteArrayAsync().Result;
// Stupid chunked requests remove the final CRLF, which makes .Net puke on the request.
// So add our own CRLF.
List<byte> crlfTemp = result.ToList();
crlfTemp.Add(0x0D);
crlfTemp.Add(0x0A);
result = crlfTemp.ToArray();
// Convert stream to MIME
using (var stream = new MemoryStream(result))
{
// 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=--MIME_boundary");
content.Headers.ContentLength = result.Length;
bool isMPC = content.IsMimeMultipartContent();
Task.Factory
.StartNew(() => parts = content.ReadAsMultipartAsync().Result.Contents.ToList(),
CancellationToken.None,
TaskCreationOptions.LongRunning, // guarantees separate thread
TaskScheduler.Default)
.Wait();
}
}