在使用 HttpWebRequest Post数据时候返回 400错误
笔者有一个项目中用到了上传zip并解压的功能。开始觉得很简单,因为之前曾经做过之类的上传文件的功能,所以并不为意,于是使用copy大法。正如你所料,如果一切很正常的能运行的话就不会有这篇笔记了。
整个系统跑起来以后,在本地开发环境中测试,顺利执行。测试环境中,顺利执行。随着项目的推进,上线。这个功能在前期本身是不重要的,不过当你没有服务器权限的时候,有一个可以随意上传文件的功能还是很不错的,再也不用写邮件,等待,等待,等待,而是可以很快看到修改结果,这样想想还是令人小激动的。 so? 出来什么问题呢?
在一套模板制作完毕并上传的时候,问题来了,这是jquery 中弹出的错误
鬼能看的懂。于是本地调整了接口,指向到本地的api,让api项目进入调试状态,再次上传文件。在费了n多调整步骤之后,抓到了错误:
远程服务器返回错误:(400)错误的请求
这是什么鬼?? 从来没见过呀!怎么没有错误提示呢??偶买噶!当时笔者的内芯是奔溃的。
立马百度,还真有好多人遇到这个问题,看了n多方案后还是跟我的情况不像。不行,那就分析吧。
笔者的程序中有这个一个函数
/// <summary>
/// 发起httpPost 请求,可以上传文件
/// </summary>
/// <param name="url">请求的地址</param>
/// <param name="files">文件</param>
/// <param name="input">表单数据</param>
/// <param name="endoding">编码</param>
/// <returns></returns>
public static string PostResponse(string url, UpLoadFile[] files, Dictionary<string, string> input, Encoding endoding)
{ string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Method = "POST";
request.KeepAlive = true;
//request.Credentials = CredentialCache.DefaultCredentials;
request.Expect = ""; MemoryStream stream = new MemoryStream(); byte[] line = Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
byte[] enterER = Encoding.ASCII.GetBytes("\r\n");
////提交文件
if (files != null)
{
string fformat = "Content-Disposition:form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type:{2}\r\n\r\n";
foreach (UpLoadFile file in files)
{ stream.Write(line, , line.Length); //项目分隔符
string s = string.Format(fformat, file.Name, file.FileName, file.Content_Type);
byte[] data = Encoding.UTF8.GetBytes(s);
stream.Write(data, , data.Length);
stream.Write(file.Data, , file.Data.Length);
stream.Write(enterER, , enterER.Length); //添加\r\n
}
} //提交文本字段
if (input != null)
{
string format = "--" + boundary + "\r\nContent-Disposition:form-data;name=\"{0}\"\r\n\r\n{1}\r\n"; //自带项目分隔符
foreach (string key in input.Keys)
{
string s = string.Format(format, key, input[key]);
byte[] data = Encoding.UTF8.GetBytes(s);
stream.Write(data, , data.Length);
} } byte[] foot_data = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n"); //项目最后的分隔符字符串需要带上--
stream.Write(foot_data, , foot_data.Length); request.ContentLength = stream.Length;
Stream requestStream = request.GetRequestStream(); //写入请求数据
stream.Position = 0L;
stream.CopyTo(requestStream); //
stream.Close(); requestStream.Close(); try
{ HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse(); try
{
using (var responseStream = response.GetResponseStream())
using (var mstream = new MemoryStream())
{
responseStream.CopyTo(mstream);
string message = endoding.GetString(mstream.ToArray());
return message;
}
}
catch (Exception ex)
{
throw ex;
}
}
catch (WebException ex)
{
//response = (HttpWebResponse)ex.Response; //if (response.StatusCode == HttpStatusCode.BadRequest)
//{
// using (Stream data = response.GetResponseStream())
// {
// using (StreamReader reader = new StreamReader(data))
// {
// string text = reader.ReadToEnd();
// Console.WriteLine(text);
// }
// }
//} throw ex;
} }
catch (Exception ex)
{
throw ex;
}
}
当然这个函数是正确的,那个错误的已经被修改掉了。
通过调试,传递进来的数据都是正确的那么问题肯定是出在http数据包的拼接上了。
出于习惯,准备把整段代码换掉,实现功能后再分析错误所在,于是百度一下 HttpWebRequest 上传文件的代码,由于我要实现的是多文件上传,那些单文件上传的例子都被我pass掉,实验了几个网上的例子后觉得还是不行。于是自己提取了数据,使用Advanced REST client(chrome插件) 工具模拟post,分析它post时候发送是数据包格式
经过自己对比,发现笔者的程序中在\n\rContent-Type之前有一个分号(;)在上文中代码的第41行处,奔溃在数据包内容部分最后的分隔符 结尾不是以 --\r\n结尾的 在上文代码中54行,于是修改了这两处及对程序做了细微的调整。并再次上传文件得到api返回结果。
至此这给bug总算搞定,不过lz写了这多多字就是为了记录这次修改的胜利么!no no no,不是那样,我是要记录一下这http post数据包的格式。
笔者随后查阅资料得到:
这个一个请求报文的格式,请求行和请求头部都可以通过 HttpWebRequest 对象的一些属性来添加,具体有哪些自己百度一下吧,笔者也不是十分清楚,这里就不给出资料了
请求数据需要自己 使用字符串拼接,下面给出笔者在这次事件中得到的经验
-------------------------------------------------------------------------------------------------------
请求数据每一个行需要以括号内的(--分隔符\r\n ) 进行分割,注意--是必须带的,例如:
"--" + boundary+"\r\n" 其中boundary 是自定义的分隔符
表单数据最后一项之后的分隔符是以 --\r\n结尾的,如下示例:
------WebKitFormBoundarydhy7IYZyMgmp2cLv--
实际上他是 "--" + boundary+"--\r\n" ,可以参考上文中代码 54行 --------------------------------------------------------------------------------------------- 读者如果觉得我讲的比较迷糊可以参考下下面这篇博文进行对比学习
http://blog.csdn.net/five3/article/details/7181521 听说Post传输数据有好几种形式哦,后续继续分析,欢迎拍砖
在使用 HttpWebRequest Post数据时候返回 400错误的更多相关文章
- HTTP请求中带有特殊字符"|",返回400错误
Java平台,服务器是Tomcat8,前端ajax访问服务器时,F12返回400错误,经分析,URL地址中get传参值里面含有“|“, Invalid character found and RFC ...
- 升级shiro1.6版本后导致附件上传失败,浏览器返回400错误
最新shiro发布了一个漏洞,凡是jar包在1.6版本的都会出现该漏洞,要修复该漏洞只能升级到shiro1.6版本 但是如果项目中url使用了;jsessionid这种方式的话 就会导致上传失败,浏览 ...
- mvn deploy返回400错误的几种可能
user credentials are wrong url to server is wrong user does not have access to the deployment reposi ...
- 解决webSocke客户端连接服务端返回400错误
原因: nginx使用了转发,头信息没设置全,问题出现在nginx的配置文件 解决办法: 修改nginx.conf配置文件,在linux终端敲入vim /etc/nginx/nginx.conf,找到 ...
- flask ajax发送请求返回400
在flaskWTF使用csrf保护后,一般提交form表单都需要一个隐藏的csrf 这样可以成功提交,但是使用ajax提交时就不能成功提交,会返回400错误,服务器无法理解请求,这样就需要新的方法解决 ...
- 由 POST 400 错误拔出来的萝卜
缘起 前段时间遇到扫描问题,好不容易拿到了扫描出来的数据,结果调用接口时弹了个 400(Bad request) 给我,匆匆找了点资料修补上线后,忐忑的心也可以安分点.然后,顺着这个 400 的萝卜, ...
- Tomcat 400错误 问题集锦
1.前后台参数类型不一致 上图错误提示就是客户端发送的请求不能找到你的具体的页面或者地址,这是Spring MVC抛出的错误,这样我们就要进行参数的检查,一定是JSP提交的参数和Controller里 ...
- nginx 设置client header 的大小与400错误
nginx默认的header长度上限是4k,如果超过了这个值 如果header头信息请求超过了,nginx会直接返回400错误可以通过以下2个参数来调整nginx的header上限 client_he ...
- post数据时报错:远程服务器返回错误: (400) 错误的请求。
网上查了多种方法,有不少说法,报400说是传的数据格式不对,最后的结论确实是数据格式不对. Content_Type为:application/json,配的数据格式有些麻烦,特别数多层,单层还好.例 ...
随机推荐
- T-SQL 实现行转列
问题: 我正在寻找一种有效的方式将行转换为SQL服务器中的列 例如,通过下表如何构建出预期结果表. Id Value ColumnName 1 John FirstName 2 2 ...
- 怎么实现ZBrush 4R7中界面视窗的快速转换
本篇教程介绍ZBrush® 4R7界面的基本操作之转换界面视窗, 教程属于入门教程可以帮助新手快速入门.因为ZBrush工 作界面不同于其他我们所熟知的3D软件,初次接触ZBrush的时候难免会有所困 ...
- jmeter(九)逻辑控制器
jmeter中逻辑控制器(Logic Controllers)的作用域只对其子节点的sampler有效,作用是控制采样器的执行顺序. jmeter提供了17种逻辑控制器,它们各个功能都不尽相同,大概可 ...
- phoneGap+cordova+ionic混合app开发环境搭建
参考链接:http://www.w2 bc.com/article/177257 待补充
- liunx关闭防火墙
Redirecting to /bin/systemctl stop iptables.service systemctl stop iptables.service ?????? centos从7开 ...
- asp.net中缓存的使用介绍一
asp.net中缓存的使用介绍一 介绍: 在我解释cache管理机制时,首先让我阐明下一个观念:IE下面的数据管理.每个人都会用不同的方法去解决如何在IE在管理数据.有的会提到用状态管理,有的提到的c ...
- 系统级性能分析工具perf的介绍与使用
测试环境:Ubuntu16.04(在VMWare虚拟机使用perf top存在无法显示问题) Kernel:3.13.0-32 系统级性能优化通常包括两个阶段:性能剖析(performance pro ...
- 基于modelsim-SE的简单仿真流程—下
基于modelsim-SE的简单仿真流程—下 编译 在 WorkSpace 窗口的 counter_tst.v上点击右键,如果选择Compile selected 则编译选中的文件,Compile A ...
- od 查看特殊格式的文件内容
用户通常使用od命令查看特殊格式的文件内容.通过指定该命令的不同选项可以以十进制.八进制.十六进制和ASCII码来显示文件. 语法: od [选项] 文件- 命令中各选项的含义: - A 指定地址基数 ...
- 【BZOJ 2595】【WC 2008】游览计划
http://www.lydsy.com/JudgeOnline/problem.php?id=2595 斯坦纳树的例题诶...我怎么做了好长时间_(:з」∠)_ 首先这是一棵树. 状压表示状态,\( ...