简体   繁体   English

使用 MultipartContent - 它工作正常,但工作正常吗?

[英]Using MultipartContent - It's working, but is it working right?

I've got a little app that generates an HttpMessage with Multipart content...我有一个小应用程序,它生成一个包含多部分内容的 HttpMessage ......

using (var client = new HttpClient())
{
    using (var content = new MultipartContent("mixed", "----123"))
    {
        content.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/mixed; boundary=----123");
        // repeated calls to content.Add(...)

        var result = client.PostAsync(url, content). Result;

        Console.WriteLine(result);
    }
}

and I have a little HttpServer that listens for POST calls and does this when it gets one...我有一个小 HttpServer 来监听 POST 调用,并在它收到一个时执行此操作......

var streamContent = new StreamContent(inputStream);
streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/mixed; boundary=----123");
var provider = streamContent.ReadAsMultipartAsync().Result;

foreach (var httpContent in provider.Contents)
{
    var t = httpContent.Headers.ContentType;
    var c = httpContent.ReadAsStringAsync().Result;
}

And it all works.这一切都有效。

But if, in my receiver code, I do not include the line streamContent.Headers.ContentType... the receiver crashes on the var provider... line with the error Invalid 'HttpContent' instance provided. It does not have a content-type header value. 'HttpContent' instances must have a content-type header starting with 'multipart/'.但是,如果在我的接收器代码中,我包括行streamContent.Headers.ContentType...接收器在var provider...提供错误Invalid 'HttpContent' instance provided. It does not have a content-type header value. 'HttpContent' instances must have a content-type header starting with 'multipart/'. Invalid 'HttpContent' instance provided. It does not have a content-type header value. 'HttpContent' instances must have a content-type header starting with 'multipart/'. . .

So, whilst I have code that works, it will only work if I know, in advance, what the boundary is going to be.因此,虽然我的代码有效,但只有在我事先知道边界将是什么时,它才会有效。

This can't be right.这不可能。

I've looked through, and tried, dozens of permutations based on questions here in SO and elsewhere but I can't find anything that works without me setting the ContentType header in the receiver and, therefore, knowing what the boundary value is.我已经查看并尝试了数十种基于 SO 和其他地方的问题的排列,但是如果没有我在接收器中设置ContentType header 并因此知道边界值是什么,我找不到任何可行的方法。

What should I be doing?该做什么?

UPDATE更新

If I remove the boundary part of the ContentType header in the receiver, it still crashes, but with a different error... Invalid 'HttpContent' instance provided. It does not have a 'multipart' content-type header with a 'boundary' parameter.如果我在接收器中删除ContentType header 的边界部分,它仍然会崩溃,但出现不同的错误...... Invalid 'HttpContent' instance provided. It does not have a 'multipart' content-type header with a 'boundary' parameter. Invalid 'HttpContent' instance provided. It does not have a 'multipart' content-type header with a 'boundary' parameter.

I don't think your server is doing what you think it is doing.我不认为你的服务器正在做你认为它正在做的事情。 new StreamContent(Stream) is used when you create your own stream content with the intent to return it from controller action.当您创建自己的 stream 内容并意图从 controller 操作返回它时,使用new StreamContent(Stream) And the stream you pass to it should contain the raw data (entity, response body) that will be returned.您传递给它的 stream 应该包含将返回的原始数据(实体、响应正文)。 It doesn't try to interpret the data from the stream in any way.它不会试图以任何方式解释来自 stream 的数据。 Even if you pass valid http stream in the parameter, it won't try to parse content-type headers from it - you have to supply it.即使您在参数中传递有效的 http stream ,它也不会尝试从中解析内容类型标头 - 您必须提供它。 And that's a big IF, you didn't show where you get the inputStream , it's not standard part of MVC.这是一个很大的 IF,你没有显示你从哪里得到inputStream ,它不是 MVC 的标准部分。

Actual content you received from client is accessible in Request.Content , along with the proper headers like content-type or boundary.您从客户端收到的实际内容可在Request.Content以及正确的标头(如内容类型或边界)中访问。 ReadAsMultipartAsync should work on that too, but I never tried that extension in practice. ReadAsMultipartAsync 也应该可以解决这个问题,但我在实践中从未尝试过该扩展。

As a side note, using Task.Result should be last resort.作为旁注,使用Task.Result应该是最后的手段。 Make your controller action async and await that task.使您的 controller 操作异步并等待该任务。

Edit: for illustration, I think this would work and doesn't require knowing the boundary in advance.编辑:为了说明,我认为这会起作用,并且不需要提前知道边界。 Still, it's very suboptimal solution when you can just call Request.Content.ReadAsMultipartAsync() :尽管如此,当您可以调用Request.Content.ReadAsMultipartAsync()时,它仍然是非常不理想的解决方案:

var streamContent = new StreamContent(inputStream);
streamContent.Headers.ContentType = Request.Content.Headers.ContentType;
                                 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
var provider = streamContent.ReadAsMultipartAsync().Result;

foreach (var httpContent in provider.Contents)
{
    var t = httpContent.Headers.ContentType;
    var c = httpContent.ReadAsStringAsync().Result;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM