如何使用 .Net 4.0 中包含的 HttpClient 类将文件上传到在 IIS Express 中运行的 Asp.Net MVC 4.0 操作

Posted

技术标签:

【中文标题】如何使用 .Net 4.0 中包含的 HttpClient 类将文件上传到在 IIS Express 中运行的 Asp.Net MVC 4.0 操作【英文标题】:How to upload files to Asp.Net MVC 4.0 action running in IIS Express with HttpClient class included in .Net 4.0 【发布时间】:2013-03-26 13:44:58 【问题描述】:

我有一个 C/S 应用程序。我用 Asp.Net MVC 4.0 实现了服务器,客户端在 .Net 4.5 上运行。

我在服务器端有一个控制器动作如下所示:

public JsonResult Upload(string arg1, int arg2)

    //do something about arg1 and arg2 here
    ...

    var files = Request.Files;
    if (files.Count > 0)
    
        foreach(var file in files)
        
            var ms = new MemoryStream();
            file.InputStream.CopyTo(ms);
            //save it to somewhere
            ...
        
    

    ...

我创建了一个测试 html 页面来在浏览器中对其进行测试。它按预期工作。

在客户端,我使用HttpClient 类,它在不涉及文件上传的情况下完美运行。然而,经过几天的研究,我仍然没有运气在运行 IIS Express 的调试机器中解决这个问题。我发现所有的线索都指向MultipartFormDataContent,但是仍然无法正常工作,即使我复制了那些示例代码,服务器端仍然无法获取任何东西,所有args都是空的,并且没有文件在里面Request.Files。我曾经有自己的基于HttpWebRequest 的http helper 类,它适用于文件上传,但我更喜欢在这个新项目中使用HttpClient。

那么,如何使用 HttpClient 将文件上传到服务器?

【问题讨论】:

请注意,我没有在 IIS 中对此进行测试,也没有使用 Asp.net MVC 3.0 对其进行测试。 【参考方案1】:

用 Fiddler 调试后,将原始 http 消息与 WinMerge 进行比较,我发现 Firefox 和我的程序之间的差异:

Firefox(删除了一些标题以使事情变得简单):

POST http://localhost:53400/Input/Upload HTTP/1.1
Host: localhost:53400
Content-Type: multipart/form-data; boundary=---------------------------1590871622043
Content-Length: ****

-----------------------------1590871622043
Content-Disposition: form-data; name="arg1"

abc
-----------------------------1590871622043
Content-Disposition: form-data; name="arg2"

3
-----------------------------1590871622043
Content-Disposition: form-data; name="uploadfile"; filename="wave.wav"
Content-Type: audio/wav

//file data here
-----------------------------1590871622043--

我的程序 MultipartFormDataContent:

POST http://localhost:53400/Input/Save HTTP/1.1
Content-Type: multipart/form-data; boundary="caac5ea7-8ab4-4682-be40-ecb3ddf3e70a"
Host: localhost:53400
Content-Length: ****

--caac5ea7-8ab4-4682-be40-ecb3ddf3e70a
Content-Disposition: form-data; name=arg1

abc
--caac5ea7-8ab4-4682-be40-ecb3ddf3e70a
Content-Disposition: form-data; name=arg2

3
--caac5ea7-8ab4-4682-be40-ecb3ddf3e70a
Content-Disposition: form-data; name=uploadfile; filename=wave.wav; filename*=utf-8''wave.wav

//file data here
--caac5ea7-8ab4-4682-be40-ecb3ddf3e70a--

我注意到的最后一件事是,在这些 Content-Disposition 行中,Firefox 引用了所有值,但我的程序没有。人们可以很容易地认为这无关紧要,但最后我发现这就是确切的原因。

现在我知道了原因,下面是有效的代码,就像引用名称一样简单:

var multipart = new MultipartFormDataContent();
multipart.Add(new StringContent("abc"), '"' + "arg1" + '"');
multipart.Add(new StringContent("3"), '"' + "arg2" + '"');

// byte[] fileData;
multipart.Add(new ByteArrayContent(fileData), '"' + "uploadfile"+ '"', '"' + "wave.wav" + '"');
//HttpClient http; string url;
var response = await http.PostAsync(url, multipart);
response.EnsureSuccessStatusCode();
//...

【讨论】:

以上是关于如何使用 .Net 4.0 中包含的 HttpClient 类将文件上传到在 IIS Express 中运行的 Asp.Net MVC 4.0 操作的主要内容,如果未能解决你的问题,请参考以下文章

如何解决从字符串加载 XSL 的转换中包含的 XSL?

我如何在 ASP.Net Core 2.1 mvc 应用程序中包含 System.Identitymodel 4.0

将单选按钮中包含的小圆圈(点)的颜色更改为红色?

ASP.NET MVC jQuery 自动完成与页面中包含的脚本中的 url.action 助手

iPhone 如何使用 Core Data 修改 Persistent store 中包含的数据

如何使用向量中包含的 double[4][4] 数组?