Multipart/form-data POST文件上传详解

理论

简单的HTTP POST

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

<form method="post"action="http://w.sohu.com" >

<inputtype="text" name="txt1">

<inputtype="text" name="txt2">

</form>

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

POST / HTTP/1.1

Content-Type:application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

Host: w.sohu.com

Content-Length: 21

Connection: Keep-Alive

Cache-Control: no-cache

txt1=hello&txt2=world

对于普通的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表单提交文件操作如下:

<form method="post"action="http://w.sohu.com/t2/upload.do" enctype=”multipart/form-data”>

<inputtype="text" name="desc">

<inputtype="file" name="pic">

</form>

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

POST /t2/upload.do HTTP/1.1

User-Agent: SOHUWapRebot

Accept-Language: zh-cn,zh;q=0.5

Accept-Charset: GBK,utf-8;q=0.7,*;q=0.7

Connection: keep-alive

Content-Length: 60408

Content-Type:multipart/form-data; boundary=ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC

Host: w.sohu.com

--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC

Content-Disposition: form-data;name="desc"

Content-Type: text/plain; charset=UTF-8

Content-Transfer-Encoding: 8bit

[......][......][......][......]...........................

--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC

Content-Disposition: form-data;name="pic"; filename="photo.jpg"

Content-Type: application/octet-stream

Content-Transfer-Encoding: binary

[图片二进制数据]

--ZnGpDtePMx0KrHh_G0X99Yef9r8JZsRJSXC--

我们来分析下数据,第一个空行之前自然还是HTTP header,之后则是Entity,而此时的Entity也比之前要复杂一些。根据RFC 1867定义,我们需要选择一段数据作为“分割边界”( boundary属性),这个“边界数据”不能在内容其他地方出现,一般来说使用一段从概率上说“几乎不可能”的数据即可。 不同浏览器的实现不同,例如火狐某次post的  boundary=---------------------------32404670520626 , opera为boundary=----------E4SgDZXhJMgNE8jpwNdOAX ,每次post浏览器都会生成一个随机的30-40位长度的随机字符串,浏览器一般不会遍历这次post的所有数据找到一个不可能出现在数据中的字符串,这样代价太大了。一般都是随机生成,如果你遇见boundary值和post的内容一样,那样的话这次上传肯定失败,不过我建议你去买彩票,你太幸运了。Rfc1867这样说明{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、Ox0A)字符作为换行,这与Windows的标准一致。如果您使用其他操作系统,则需要考虑它们的换行符

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

实现

httpClient4如何实现

httpClient4使用http-mime.jar包的MultipartEntity实现,代码如下(为了简洁,处理了异常处理代码):

HttpPost httpPost = newHttpPost(url);

Log.debug("post url:"+url);

httpPost.setHeader("User-Agent","SOHUWapRebot");

httpPost.setHeader("Accept-Language","zh-cn,zh;q=0.5");

httpPost.setHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.7");

httpPost.setHeader("Connection","keep-alive");

MultipartEntity mutiEntity = newMultipartEntity();

File file = new File("d:/photo.jpg");

mutiEntity.addPart("desc",new StringBody("美丽的西双版纳", Charset.forName("utf-8")));

mutiEntity.addPart("pic", newFileBody(file));

httpPost.setEntity(mutiEntity);

HttpResponse  httpResponse = httpClient.execute(httpPost);

HttpEntity httpEntity =  httpResponse.getEntity();

String content = EntityUtils.toString(httpEntity);

Multipart/form-data POST文件上传详解(转)的更多相关文章

  1. Multipart/form-data POST文件上传详解

    Multipart/form-data POST文件上传详解 理论 简单的HTTP POST 大家通过HTTP向服务器发送POST请求提交数据,都是通过form表单提交的,代码如下: <form ...

  2. 文件上传详解 (HTML FILE)

    FileUpload 对象 在 HTML 文档中 <input type="file"> 标签每出现一次,一个 FileUpload 对象就会被创建. 该元素包含一个文 ...

  3. 摘抄--使用cos实现多个文件上传详解

    在开发中常常需要上传文件,上传文件的方式有很多种,这里有一个cos实现的例子. 首先是要拷贝cos.jar包拷贝到WEB-INF/lib目录下,然后才进行编码. 创建一个可以进行自动重命名的Java文 ...

  4. SWFUpload文件上传详解

    SWFUpload是一个flash和js相结合而成的文件上传插件,其功能非常强大. SWFUpload的特点: 1.用flash进行上传,页面无刷新,且可自定义Flash按钮的样式; 2.可以在浏览器 ...

  5. 【转】JSch - Java实现的SFTP(文件上传详解篇)

    JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到 ...

  6. JSch - Java实现的SFTP(文件上传详解篇)

    JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到 ...

  7. JSch - Java实现的SFTP(文件上传详解篇) [转载]

    文章来源:http://www.cnblogs.com/longyg/archive/2012/06/25/2556576.html JSch是Java Secure Channel的缩写.JSch是 ...

  8. JSch - Java实现的SFTP(文件上传详解篇)(转)

    JSch是Java Secure Channel的缩写.JSch是一个SSH2的纯Java实现.它允许你连接到一个SSH服务器,并且可以使用端口转发,X11转发,文件传输等,当然你也可以集成它的功能到 ...

  9. Java大文件上传详解及实例代码

    1,项目调研 因为需要研究下断点上传的问题.找了很久终于找到一个比较好的项目. 在GoogleCode上面,代码弄下来超级不方便,还是配置hosts才好,把代码重新上传到了github上面. http ...

随机推荐

  1. What does cmd /C mean? [closed] 关于nodejs的子进程部分

    之前一直很不明白为什么 child_process.spawn(command[, args][, options]) shell <Boolean> | <String> I ...

  2. SDK Manager 报错:Connection timed out: connect

    安装Eclipse的安卓开发环境的时候,安装sdk时报错,出现: 解决办法: 1.选择左上角的Tools 2.选择Options,勾选下面红色框的东西 3. 4.重新重启一下sdk manager即可

  3. html5本地存储 local storage

    HTML5 web storage, a better local storage than cookies. With HTML5, web pages can store data locally ...

  4. java设计模式--行为型模式--命令模式

    命令模式 概述 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作. 适用性 .抽象出待执行的动作以参数化某对象. .在不同的时刻指定.排 ...

  5. alternaiate terms

    操作系统就是能让您的计算机工作 的一系列基本程序和实用工具; 大多数的软件至少都要卖几百块钱,您们怎么愿意白白把它送给别人? 您真正应该问的问题是软件公司怎么可以要您花那么多钱买他们的软件.写软件和制 ...

  6. node.async.auto

    资料 GITHUB async ASYNC详解—from csdn nodejs的高性能与灵活性让服务端开发变得有了些乐趣,最近在看nodejs在服务端的一些应用,觉得其npm下的众多开源包让其虽没有 ...

  7. ubuntu下google 拼音输入法的安装

    google拼音输入法安装 (1).获代替码:(没有git的先安装git:sudoapt-get install git-core) $>gitclone git://github.com/tc ...

  8. Codeforces 551C GukiZ hates Boxes 二分答案

    题目链接 题意:  一共同拥有n个空地(是一个数轴,从x=1 到 x=n),每一个空地上有a[i]块石头  有m个学生  目标是删除全部石头  一開始全部学生都站在 x=0的地方  每秒钟每一个学生都 ...

  9. Wheel ProgressBar 实现之三——模拟进度过程

    1. 效果展示: 知道如何画圆弧,如何精确画出进度文本之后,我们将进入 Wheel ProgressBar 实现的最后一个过程:模拟其动态呈现过程.如下图所示,初始时显示进度为 0 (上图),点击进度 ...

  10. 微信内移动前端开发抓包调试工具fiddler使用教程

    在朋友圈看到一款疯转的H5小游戏,想要copy,什么?只能在微信里打开?小样,图样图森破,限制了oauth.微信浏览器内打开,照样能看你源码~ 使用fiddler来抓包 需要先做一些简单的准备工作: ...