使用 HttpClient 进行表单提交时,遇到的问题
2019-12-29 11:35
1861 查看
问题
在开发微信支付的小微商户进件接口时,需要通过表单来上传身份证图片等数据。在微信支付接口文档也说明了,需要使用 multipart/form-data 的方式发送请求。.NET 提供了
MultipartFormDataContent类型,帮助我们构建表单请求,故有以下代码:
var form = new MultipartFormDataContent() { {new StringContent("Value"),"Name}, {new ByteArrayContent(new byte[]{}/*模拟文件数据*/),"File,"FileName} }
按照微信支付官方文档提交之后,一直提示参数错误,百思不得其解。
原因
通过 Postman 模拟表单提交,捕获数据包,将其与 C# 的提交代码进行对比,发现了两处问题。
Postman 的原始提交:
POST http://api.mch.weixin.qq.com/secapi/mch/uploadmedia HTTP/1.1 User-Agent: PostmanRuntime/7.21.0 Accept: */* Cache-Control: no-cache Postman-Token: b6800c0f-3f16-4981-b661-e6d16fc1bb1e Host: api.mch.weixin.qq.com Content-Type: multipart/form-data; boundary=--------------------------639275760242036520206377 Accept-Encoding: gzip, deflate Content-Length: 566 Connection: keep-alive ----------------------------639275760242036520206377 Content-Disposition: form-data; name="mch_id" 1565111111 ----------------------------639275760242036520206377 Content-Disposition: form-data; name="media_hash" 7215E92A8F3F3D0256484EFFF53A25F6 ----------------------------639275760242036520206377 Content-Disposition: form-data; name="sign_type" HMAC-SHA256 ----------------------------639275760242036520206377 Content-Disposition: form-data; name="sign" A1D8B094FA24BE5531D1AC198DE25550 ----------------------------639275760242036520206377--
C# 代码的提交:
POST http://api.mch.weixin.qq.com/secapi/mch/uploadmedia HTTP/1.1 Host: api.mch.weixin.qq.com Content-Type: multipart/form-data; boundary="e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217" Content-Length: 502 --e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217 Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=mch_id --e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217 Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=media_hash 33F15BC2D17D6FFBC18FA566EF65722E --e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217 Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=sign 1E377684F9BD583D2ED26FB367916C0C --e9d5712f-7923-4ec5-8bf3-c8d5d3cd3217--
1. Boundary 的双引号
使用
MultipartFormDataContent提交的表单请求,外部
Content-Type的
boundary值带有
"号。而 Postman 提交的表单请求,它的
boudary值是没有双引号的。
那为什么会造成这样的差异呢?参考 这篇 博客的讲解,是由于各个系统/语言针对 RFC 2046 的实现不一致导致的。针对于
MultipartFormDataContent的行为,如果 Boundary 后面的值带有双引号是符合标准的。
RFC 2612 原文:
2) Although RFC 2046 [40] permits the boundary string to be
quoted, some existing implementations handle a quoted boundary
string incorrectly.
Boundary 的作用,是一个随机生成的字符串,在 HTTP 协议当中用于分割内部多个 Content。为什么是随机生成的呢?就是防止这个分割符跟你内部的 Content 产生重复造成意外。(C# 默认使用的是 Guid 作为随机串,你也可以在构造
MultipartFormDataContent的时候,通过其构造函数手动指定)
2. 表单内键值对,值的双引号
第二个问题则是表单内的内容,他们的
name键值对,其值又没有双引号,所以你得在添加 Content 的时候,得手动指定双引号。
解决
两个问题都是由于双引号导致的,所以只需要在真正发起调用之前将内部的双引号替换为空,或者将缺失的双引号添加上即可。
针对问题一,其内部的
ContentType.Parameters,通过 LINQ 找到
boundary的键值对,替换内部的双引号即可。
var boundaryValue = form.Headers.ContentType.Parameters.Single(p => p.Name == "boundary"); boundaryValue.Value = boundaryValue.Value.Replace("\"", String.Empty);
针对问题二,在构造内部 Content 的时候,其 Name 手动赋予双引号。
var form = new MultipartFormDataContent { {new StringContent(mchId), "\"mch_id\""}, {new ByteArrayContent(bytes), "media", $"\"{HttpUtility.UrlEncode(Path.GetFileName(imagePath))}\""}, {new StringContent(mediaHash), "\"media_hash\""}, {new StringContent(sign), "sign"} };
相关文章推荐
- IE6利用Javascript进行表单提交遇到的问题
- 当button按钮放入form表单进行ajax提交遇到的诡异问题
- 当button按钮放入form表单进行ajax提交遇到的诡异问题
- 当button按钮放入form表单进行ajax提交遇到的诡异问题
- 当button按钮放入form表单进行ajax提交遇到的诡异问题
- 当button按钮放入form表单进行ajax提交遇到的诡异问题
- 当button按钮放入form表单进行ajax提交遇到的诡异问题
- 当button按钮放入form表单进行ajax提交遇到的诡异问题
- 使用HttpClient的post提交数据遇到的问题
- 表单包含file上传文件提交,使用ajaxSubmint或者ajaxForm 遇到的问题以及解决方法
- 关于使用js进行表单提交操作引发的表单重复提交问题
- 当button按钮放入form表单进行ajax提交遇到的诡异问题
- JQuery中使用ajax提交表单遇到的问题
- 当button按钮放入form表单进行ajax提交遇到的诡异问题
- 在spring中使用quartz进行任务调度遇到的问题
- windows使用libvlc进行网络串流遇到的一些问题及解决方法
- 关于在frame或iframe使用filter进行提交主页转向问题
- 表单提交按钮时图片时遇到的问题
- liferay中使用jQuery Validation Engine进行ajax验证,不通过也提交表单的解决方案
- input file 在开发中遇到的问题 类似ajax form表单提交 input file中的文件