HttpClient上传MultipartFormData来玩2框架

我在使用RestSharp客户端的Windows Phone 8项目中有以下代码:

public async Task DoMultiPartPostRequest(String ext, JSonWriter jsonObject, ObservableCollection attachments) { var client = new RestClient(DefaultUri); // client.Authenticator = new HttpBasicAuthenticator(username, password); var request = new RestRequest(ext, Method.POST); request.RequestFormat = DataFormat.Json; request.AddParameter("json", jsonObject.ToString(), ParameterType.GetOrPost); // add files to upload foreach (var a in attachments) request.AddFile("attachment", a.FileBody, "attachment.file", a.ContType); var content = await client.GetResponseAsync(request); if (content.StatusCode != HttpStatusCode.OK) return "error"; return content.Content; } 

Fiddler显示生成的标题:

 POST http://192.168.1.101:9000/rayz/create HTTP/1.1 Content-Type: multipart/form-data; boundary=-----------------------------28947758029299 Content-Length: 71643 Accept-Encoding: identity Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml User-Agent: RestSharp 104.1.0.0 Host: 192.168.1.101:9000 Connection: Keep-Alive Pragma: no-cache -------------------------------28947758029299 Content-Disposition: form-data; name="json" { "userId": "2D73B43390041E868694A85A65E47A09D50F019C180E93BAACC454488F67A411", "latitude": "35.09", "longitude": "33.30", "accuracy": "99", "maxDistance": "dist", "Message": "mooohv" } -------------------------------28947758029299 Content-Disposition: form-data; name="attachment"; filename="attachment.file" Content-Type: image/jpeg ?????JFIF??`?`?????C? $" &0P40,,0bFJ:Ptfzxrfpn????????np????????|????????????C"$$0*0^44^?p??????????????????????????????????????????????????????`?"?????????????? -------------------------------28947758029299 

上面的代码在Play2 API上运行良好。 但是由于RestSharp似乎不稳定,我决定使用Microsoft提供的本机HttpClient。

因此我编写了另一个使用HttpClient执行相同工作的函数:

 public async Task DoMultiPartPostRequest2(String ext, JSonWriter jsonObject, ObservableCollection attachments) { var client = new HttpClient(); var content = new MultipartFormDataContent(); var json = new StringContent(jsonObject.ToString()); content.Add(json, "json"); foreach (var a in attachments) { var fileContent = new StreamContent(new MemoryStream(a.FileBody)); fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { Name = "attachment", FileName = "attachment.file" }; fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(a.ContType); content.Add(fileContent); } var resp = await client.PostAsync(DefaultUri + ext, content); if (resp.StatusCode != HttpStatusCode.OK) return "error"; var reponse = await resp.Content.ReadAsStringAsync(); return reponse; } 

从该代码生成的标头如下:

 POST http://192.168.1.101:9000/rayz/create HTTP/1.1 Accept: */* Content-Length: 6633 Accept-Encoding: identity Content-Type: multipart/form-data; boundary="e01b2196-d24a-47a2-a99b-e82cc4a2f92e" User-Agent: NativeHost Host: 192.168.1.101:9000 Connection: Keep-Alive Pragma: no-cache --e01b2196-d24a-47a2-a99b-e82cc4a2f92e Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=json { "userId": "2D73B43390041E868694A85A65E47A09D50F019C180E93BAACC454488F67A411", "latitude": "35.09", "longitude": "33.30", "accuracy": "99", "maxDistance": "dist", "Message": "test" } --e01b2196-d24a-47a2-a99b-e82cc4a2f92e Content-Disposition: form-data; name=attachment; filename=attachment.file Content-Type: image/jpeg ?????JFIF??`?`?????C? $" &0P40,,0bFJ:Ptfzxrfpn????????np????????|????????????C"$$0*0^44^?p????????????????????????????????????????????????????????"?????????????? --e01b2196-d24a-47a2-a99b-e82cc4a2f92e-- 

到现在为止还挺好。 从我的角度来看,两个标题似乎是相同的。

但是,当我在执行Http.MultipartFormData body = request().body().asMultipartFormData();之后调试Play 2 API时 我注意到多部分数据没有被正确解析。

更具体地说,body变量中的multipart字段如下:

 MultipartFormData(Map(),List(),List(BadPart(Map(ntent-type -> text/plain; charset=utf-8, content-disposition -> form-data; name=json)), BadPart(Map()), BadPart(Map()), BadPart(Map()), BadPart(Map())),List()) 

你可以注意到它有几个(在这个例子中实际上是5个)BadParts。 示例: BadPart(Map(ntent-type -> text/plain; charset=utf-8, content-disposition -> form-data; name=json))

谁能看到这里出了什么问题? HttpClient生成的标头是错误的吗?

这是解决方案..(黑客)

当边界中有引号时,Play Framework似乎存在问题。

所以我创建multipart后添加了以下代码以删除它们:

 var content = new MultipartFormDataContent(); foreach (var param in content.Headers.ContentType.Parameters.Where(param => param.Name.Equals("boundary"))) param.Value = param.Value.Replace("\"", String.Empty); 

最后,我必须手动将标题“\”“添加到标题上的特定值,如下所示:

原文: Content-Disposition: form-data; name=attachment; filename=attachment.file Content-Disposition: form-data; name=attachment; filename=attachment.file Content-Disposition: form-data; name=attachment; filename=attachment.file更改为: Content-Disposition: form-data; name="attachment"; filename="attachment.file" Content-Disposition: form-data; name="attachment"; filename="attachment.file"

原文: Content-Disposition: form-data; name=json Content-Disposition: form-data; name=json更改为: Content-Disposition: form-data; name="json" Content-Disposition: form-data; name="json"

我认为在标题中的任何地方都没有引号是错误的,也许应该相应地修改play框架上的解析。