C#StreamContent和File.OpenRead()不产生HTTP'able的多部分内容 [英] C# StreamContent and File.OpenRead() Not Producing HTTP'able multipart content

查看:307
本文介绍了C#StreamContent和File.OpenRead()不产生HTTP'able的多部分内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个.Net Core 2.0应用程序,该应用程序使用多部分内容将文件发送到Web API端点.我到过的所有地方,例如 C#HttpClient 4.5 multipart/form -data upload ,似乎应该像将FileStream传递给StreamContent一样容易.但是,当我发布帖子时,看起来文件是作为文本而不是位附加的.

I have a .Net Core 2.0 application that is sending files to a Web API endpoint, using multipart content. Everywhere I've looked, such as C# HttpClient 4.5 multipart/form-data upload, makes it seem that it should be as easy as passing a FileStream to a StreamContent. However, when I make the post, it looks like the file is attaching as text, not bits.

实际代码:

var request = new HttpRequestMessage()
{
    Method = HttpMethod.Post,
    RequestUri = new Uri( "http://localhost:10442/filetest" )
};
var multiContent = new MultipartFormDataContent();

var filestream = File.OpenRead( path );
var filename = Path.GetFileName( path );
var streamContent = new StreamContent( filestream );
streamContent.Headers.Add( "Content-Type", "application/octet-stream" );
streamContent.Headers.Add( "Content-Disposition", $"form-data; name=\"file1\"; filename=\"{filename}\"" );

multiContent.Add( streamContent, "file", filename );
request.Content = multiContent;

var response = await new HttpClient().SendAsync( request );

您可能会注意到,请求看起来像这样,并非全部都在一行上(我认为这是一个/THE问题):

The request looks like this which, as you may notice, is not all on one line (which I think is a/THE problem):

POST http://localhost:10442/filetest HTTP/1.1
Content-Type: multipart/form-data; boundary="c5295887-425d-4ec7-8638-20c6254f9e4b"
Content-Length: 88699
Host: localhost:10442

--c5295887-425d-4ec7-8638-20c6254f9e4b
Content-Type: application/octet-stream
Content-Disposition: form-data; name="file1"; filename="somepdf.pdf"

%PDF-1.7
%       
1 0 obj
<</Type/Catalog/Version/1.7/Pages 3 0 R/Outlines 2 0 R/Names 8 0 R/Metadata 31 0 R>>
endobj

Fiddler一直显示整个帖子直到结束边界,但是端点中的await Request.Content.ReadAsStringAsync()仅显示前几个字节(看起来流还没有结束,但是如果Fiddler掌握了所有内容,我的端点不应该也有吗?).

Fiddler shows the entire post all the way down to the end boundary, but await Request.Content.ReadAsStringAsync() in the endpoint only shows the first couple dozen bytes (it looks as if the stream wasn't finished, but if Fiddler got it all, shouldn't my endpoint have too?).

在尝试击中远程端点时,我遇到了类似的麻烦;我建立了此端点以进行本地测试.

I was having similar trouble trying to hit a remote endpoint; I built this endpoint to test locally.

我得到的异常是:"MIME分段流意外结束.MIME分段消息不完整."对于我来说,这既有意义,无论我是真的只是流中的一部分,还是换行符引发了一些麻烦.

The exception I'm getting is:"Unexpected end of MIME multipart stream. MIME multipart message is not complete." To me, this makes sense both if I'm really only getting part of my stream, or if the line breaks are throwing something off.

我也曾尝试将一些Idisposables扔到Usings中,但是,正如预期的那样,它关闭了流并以这种方式获得了异常.

I have also tried throwing some of the Idisposables into Usings but, as expected, that closes the streams and I get exceptions that way.

为了完整起见,这是我要呼叫的端点:

And for completeness's sake, here's the endpoint I'm calling:

public async void ReceiveFiles()
{
    // exception happens here:
    var mpData = await Request.Content.ReadAsMultipartAsync();
    await Task.FromResult( 0 );
}

推荐答案

尝试如下操作:

static int Main(string[] args)
{
    var request = new HttpRequestMessage()
    {
        Method = HttpMethod.Post,
        RequestUri = new Uri("http://localhost:10442/filetest")
    };
    var path = "c:\\temp\\foo.bak";

    using (var filestream = File.OpenRead(path))
    {
        var length = filestream.Length.ToString();
        var streamContent = new StreamContent(filestream);
        streamContent.Headers.Add("Content-Type", "application/octet-stream");
        streamContent.Headers.Add("Content-Length", length);


        request.Content = streamContent;

        Console.WriteLine($"Sending {length} bytes");
        var response = new HttpClient().SendAsync(request).Result;


        Console.WriteLine(response.Content.ReadAsStringAsync().Result);
    }

    Console.WriteLine("Hit any key to exit");
    Console.ReadKey();
    return 0;
}

    [HttpPost]
    public async Task<IActionResult> Upload()
    {
        var buf = new byte[1024 * 64];
        long totalBytes = 0;
        using (var rs = Request.Body)
        {
            while (1 == 1)
            {
                int bytesRead = await rs.ReadAsync(buf, 0, buf.Length);
                if (bytesRead == 0) break;
                totalBytes += bytesRead;
            }
        }
        var uploadedData = new
        {
            BytesRead = totalBytes
        };
        return new JsonResult(uploadedData) ;
    }

这篇关于C#StreamContent和File.OpenRead()不产生HTTP'able的多部分内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆