转自:https://blog.csdn.net/zhangge3663/article/details/81218488

理论

简单的HTTP POST

大家通过HTTP向服务器发送POST请求提交数据,都是通过form表达提交的,代码如下:

  1. <form method="post" action="http://w.sohu.com">
  2. <input type="text" name="txt1">
  3. <input type="text" name="txt2">
  4. </form>

提交时会向服务器段发出这样的数据(已经去除部分不相关的头信息),数据如下:

  1. POST / HTTP/1.1
  2. Content-Type:application/x-www-form-urlencoded
  3. Accept-Encoding: gzip, deflate
  4. Host: w.sohu.com
  5. Content-Length: 21
  6. Connection: Keep-Alive
  7. Cache-Control: no-cache
  8.  
  9. txt1=hello&txt2=world
  10.  

对于普通的HTML Form POST请求,它会在头信息里使用Content-Length注明内容长度。头信息每行一条,空行之后便是Body,即"内容"(entity)。它的Content-Type是application/x-www-form-urlencoded,这意味着消息内容会经过URL编码,就像在GET请求时URL里的QueryString那样。txt1=hello&txt2=world.

POST上传文件

最早的HTTP POST是不支持文件上传的,给编程开发带来很多问题。但是在1995年,ietf出台了rfc1867,也就是<RFC 1867-Form-based File Upload in HTML>,用以支持文件上传。所以Content-Type的类型扩充了multipart/form-data用以支持向服务器发送二进制数据。因此发送post请求时候,表单<form>属性enctype共有两个值可选,这个属性管理的是表单的MIME编码:

①application/x-www-form-urlencoded(默认值)

②multipart/form-data

其实form表单在你不写enctype属性时,也默认为其添加了enctype属性值,默认值是enctype="application/x-www-form-urlencoded".

通过form表单提交文件操作如下:

  1. <form method="post" action="http://w.sohu.com/t2/upload.do" enctype="multipart/form-data">
  2. <input type="text" name="desc">
  3. <input type="file" name="pic">
  4. </form>

浏览器将会发送以下数据:

  1. POST /t2/upload.do HTTP/1.1
  2. User-Agent: SOHUWapRebot
  3. Accept-Language: zh-cn,zh;q=0.5
  4. Accept-Charset: GBK,utf-8;q=0.7,*;q=0.7
  5. Connection: keep-alive
  6. Content-Length: 60408
  7. Content-Type: multipart/form-data;boundary=ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
  8. Host: w.sohu.com
  9.  
  10. --ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
  11. Content-Disposition: form-data;name="desc"
  12. Content-Type: text/plain; charset=UTF-8
  13. Content-Transfer-Encoding: 8bit
  14.  
  15. [......][......][......][......]..........
  16. --ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC
  17. Content-Disposition: form-data;name="pic";filename="photo.jpg"
  18. Content-Type: application/octet-stream
  19. Content-Transfer-Encoding: binary
  20.  
  21. [图片二进制数据]
  22. --ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC--
  23.  

我们来分析下数据,第一个空行之前自然还是HTTP header,之后则是Entity,而此时的Entity也比之前要复杂一些。根据RFC 1867定义,我们需要选择一段数据作为"分隔边界"(boundary属性),这个"边界数据"不能在内容其他地方出现,一般来说使用一段从概率上说"几乎不可能"的数据即可。不同的浏览器的实现不同,例如火狐某次post的boundary=---------------------------32404670520626 ,opera为 boundary=----------E4SgDZXhJMgNE8jpwNdOAX ,每次post浏览器都会生成一个随机的30-40位长度的随机字符串,浏览器一般不会遍历这次post的所有数据找到一个不可能出现的数据中的字符串,这样代价太大了。一般都是随机生成, 如果你遇见boundary值和post的内容一样,那样的话这次上传肯定失败,不过我建议你去买彩票,你太幸运了。rfc 1867这样说明{A boundary is selected that does not occur in any of the data.(This selection is sometimes done probabilisticly.)}。

选择了这个边界之后,浏览器便把它放在Content-Type里面传递给服务器,服务器根据此边界解析数据。下面的数据便根据boundary划分段,每一段便是一项数据。(每个field被分成小部分,而且包含一个value是"form-data"的“Content-Disposition"的头部;一个"name"属性对应field的ID,等等,文件的话包括一个filename).

  • IE和Chrome在filename的选择策略上有所不同,前者是文件的完整路径,而后者则仅仅是文件名。
  • 数据内容以两条横线结尾,并同样以一个换行结束。在网络协议中一般都以连续的CR、LF(即\r、\n,或0x0D, 0x0A)字符作为换行,这与Windows的标准一致。如果您使用其他操作系统,则需要考虑他们的换行符。

另外Content-length指的是所用数据的长度。

实现

httpClient4如何实现

httpClient4使用http-mime.jar包的MultipartEntity实现,代码如下:

  1. HttpPost httpPost = newHttpPost(url);
  2. Log.debug("post url:"+url);
  3. httpPost.setHeader("User-Agent", "SOHOWapRebot");
  4. httpPost.setHeader("Accept-Language", "zh-cn,zh;q=0.5");
  5. httpPost.setHeader("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.7");
  6. httpPost.setHeader("Connection", "keep-alive");
  7.  
  8. MultipartEntity multiEntity = new MultipartEntity();
  9. File file = new File("d:/photo.jpg");
  10. multiEntity.addPart("desc", new StringBody("美丽的西双版纳", Charset.forName("utf-8")));
  11. multiEntity.addPart("pic", newFileBody(file));
  12.  
  13. httpPost.setEntity(multiEntity);
  14. HttpResponse httpResponse = httpClient.execute(httpPost);
  15. HttpEntity httpEntity = httpResponse.getEntity();
  16. String content = EntityUtils.toString(httpEntity);

通过POST请求上传文件的更多相关文章

  1. SpringMVC实现PUT请求上传文件

    在JQuery中,我们可以进行REST ful中delete和put的请求,但是在java EE标准中,默认只有在POST请求的时候,servlet 才会通过getparameter()方法取得请求体 ...

  2. Postman Post请求上传文件

    Postman Post请求上传文件一.选择post请求方式,输入请求地址 二.填写Headers Key:Content-Type :Value:multipart/form-data 如下图 三. ...

  3. SSM框架下,使用ajax请求上传文件(doc\docx\excel\图片等)

    1.准备工作 1.1.添加上传必要jar包 <dependency> <groupId>commons-io</groupId> <artifactId> ...

  4. python中使用multipart/form-data请求上传文件

    最近测试的接口是上传文件的接口,上传单个文件,我主要使用了2种方法~ 接口例如: URL: http://www.baidu.com/*** method:post 参数: { "salar ...

  5. element-ui上传组件,通过自定义请求上传文件

    记录使用element-ui上传组件,通过自定义请求上传文件需要注意的地方. <el-upload ref="uploadMutiple" :auto-upload=&quo ...

  6. JAVA模拟HTTP post请求上传文件

    在开发中,我们使用的比较多的HTTP请求方式基本上就是GET.POST.其中GET用于从服务器获取数据,POST主要用于向服务器提交一些表单数据,例如文件上传等.而我们在使用HTTP请求时中遇到的比较 ...

  7. upload三种上传方式(上)---Servlet---post---commons-fileupload.1.2.1.jar方式请求上传文件

    上传前进行的配置选项: 1.在下方的Servers中,右键你的tomcat--open,选中下面两个配置. 第一个:Serve modules without publishing 作用:tomcat ...

  8. 通过PHP CURL模拟请求上传文件|图片。

    现在有一个需求就是在自己的服务器上传图片到其他服务器上面,过程:客户端上传图片->存放到本地服务器->再转发到第三方服务器; 由于前端Ajax受限制,只能通过服务器做转发了. 在PHP中通 ...

  9. python发送post请求上传文件,无法解析上传的文件

    前言 近日,在做接口测试时遇到一个奇葩的问题. 使用post请求直接通过接口上传文件,无法识别文件. 遇到的问题 以下是抓包得到的信息: 以上请求是通过Postman直接发送请求的. 在这里可以看到消 ...

随机推荐

  1. 将实体转换为Hashtable

    1.将实体转换为Hashtable,用于将实体参数处理为hashtable,方便sql参数传递 /// <summary> /// 将实体转换为Hashtable /// </sum ...

  2. python中的函数(基础)

    1.什么是函数 函数是指将一组数据的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用函数名即可 (函数就是对功能或者动作的封装) 2.函数的语法和定义 def 函数名() 函数体 调用: ...

  3. RPC 简单小试

    由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里 RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器 ...

  4. “全栈2019”Java多线程第十四章:线程与堆栈详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  5. HDU 3007 模拟退火算法

    Buried memory Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  6. iphone 自学常用网址

    https://www.gitbook.com/book/numbbbbb/-the-swift-programming-language-/details https://github.com/ip ...

  7. P5038 [SCOI2012]奇怪的游戏

    题目链接 题意分析 首先我们需要求的是统一以后的值\(x\) 并且一般的棋盘操作我们都需要黑白染色 那么对于棋盘格子是偶数的情况的话 答案是存在单调性的 因为如果统一之后 两两搭配还是可以再加一个的 ...

  8. 架构师养成记--22.客户端与服务器端保持连接的解决方案,netty的ReadTimeoutHandler

    概述 保持客户端与服务器端连接的方案常用的有3种 1.长连接,也就是客户端与服务器端一直保持连接,适用于客户端比较少的情况. 2.定时段连接,比如在某一天的凌晨建立连接,适用于对实时性要求不高的情况. ...

  9. 电信10兆指的是多少Mbps

    一般电信10兆(10Mbps)指的是:下载速度最大在1.25MB/s 1Mbps(兆位/秒)     =     0.125MB/S(兆字节/秒) 8Mbps(兆位/秒)     =     1MB/ ...

  10. CentOS 7 安装方式汇总

    U盘安装 通过U盘安装 CentOS 的过程和安装Windows非常相似,首先将 CentOS 镜像文件刻录到U盘(或者光盘),设置固件(BIOS或者UEFI)从U盘启动,然后逐步设置即可. 使用 V ...