博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
上传文件multipart form-data boundary 说明
阅读量:5927 次
发布时间:2019-06-19

本文共 3837 字,大约阅读时间需要 12 分钟。

含义 ENCTYPE="multipart/form-data" 说明:

通过 http 协议上传文件 rfc1867协议概述,客户端发送内容构造。

概述                                                                                           

在最初的 http 协议中,没有上传文件方面的功能。 rfc1867为 http 协议添加了这个功能。客户端的浏览器,如 Microsoft IE, Mozila, Opera 等,按照此规范将用户指定的文件发送到服务器。服务器端的网页程序,如 php, asp, jsp 等,可以按照此规范,解析出用户发送来的文件。Microsoft IE, Mozila, Opera 已经支持此协议,在网页中使用一个特殊的 form 就可以发送文件。绝大部分 http server ,包括 tomcat ,已经支持此协议,可接受发送来的文件。各种网页程序,如 php, asp, jsp 中,对于上传文件已经做了很好的封装。

实例                                                                                           

注意 enctype="multipart/form-data", method=post, type="file" 。根据 rfc1867, 这三个属性是必须的。multipart/form-data 是新增的编码类型,以提高二进制文件的传输效率。

数据传输                                                                                      

格式 必须一字不差,包括最后的回车。

注意:Content-Length: 226 这里的226是红色内容的总长度(包括最后的回车)

注意这一行:

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

根据 rfc1867, multipart/form-data是必须的.---------------------------7d33a816d302b6 是分隔符,分隔多个文件、表单项。

其中7d33a816d302b6 是即时生成的字符串,用以确保整个分隔符不会在文件或表单项的内容中出现。

使用POST发送数据                                                                      

以POST方式发送数据主要是为了向服务器发送较大量的客户端的数据,它不受URL的长度限制。POST请求将数据以URL编码的形式放在HTTP正文中,字段形式为fieldname=value,用&分隔每个字段。注意所有的字段都被作为字符串处理。实际上我们要做的就是模拟浏览器POST 一个表单。以下是IE发送一个登陆表单的POST请求:

POST http://127.0.0.1/login.do HTTP/1.0Accept: image/gif, image/jpeg, image/pjpeg, */*Accept-Language: en-us,zh-cn;q=0.5Content-Type: application/x-www-form-urlencodedUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)Content-Length: 28
 
username=admin&password=1234

要在MIDP应用程序中模拟浏览器发送这个POST请求,首先设置HttpConnection的请求方式为POST(PHP为curl):

// 使用POST方法              httpURLConnection.setRequestMethod("POST");

然后构造出HTTP正文:

byte[] data = "username=admin&password=1234".getBytes();

并计算正文长度,填入Content-Type和Content-Length:

httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");httpURLConnection.setRequestProperty("Content-Length", String.valueOf(data.length));

然后打开OutputStream将正文写入:

OutputStream output = hc.openOutputStream();output.write(data);

需要注意的是,数据仍需要以URL编码格式编码,由于MIDP库中没有J2SE中与之对应的URLEncoder类,因此,需要自己动手编写这个 encode()方法,可以参考java.net.URLEncoder.java的源码。剩下的便是读取服务器响应,代码与GET一致,这里就不再详述。

使用multipart/form-data发送文件                                             

如果要在MIDP客户端向服务器上传文件,我们就必须模拟一个POST multipart/form-data类型的请求,Content-Type必须是multipart/form-data。

以multipart/form-data编码的POST请求格式与application/x-www-form-urlencoded完全不同,multipart/form-data需要首先在HTTP请求头设置一个分隔符,例如ABCD:

httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=ABCD");

然后,将每个字段用“--分隔符”分隔,最后一个“--分隔符--”表示结束。例如,要上传一个title字段"Today"和一个文件C:\1.txt,HTTP正文如下:

--ABCDContent-Disposition: form-data; name="title"\r\nToday--ABCDContent-Disposition: form-data; name="1.txt"; filename="C:\1.txt"Content-Type: text/plain\r\n
<这里是1.txt文件的内容>
--ABCD--\r\n

请注意,每一行都必须以\r\n结束,包括最后一行。如果用Sniffer程序检测IE发送的POST请求,可以发现IE的分隔符类似于 ---------------------------7d4a6d158c9,这是IE产生的一个随机数,目的是防止上传文件中出现分隔符导致服务器无法正确识别文件起始位置。我们可以写一个固定的分隔符,只要足够复杂即可。

发送文件的POST代码如下:

String[] props = ... // 字段名String[] values = ... // 字段值byte[] file = ... // 文件内容String BOUNDARY = "---------------------------7d4a6d158c9"; // 分隔符StringBuffer sb = new StringBuffer();// 发送每个字段:for(int i=0; isb = sb.append("--");sb = sb.append(BOUNDARY);sb = sb.append("\r\n");sb = sb.append("Content-Disposition: form-data; name=\""+ props[i] + "\"\r\n\r\n");sb = sb.append(URLEncoder.encode(values[i]));sb = sb.append("\r\n");}// 发送文件:sb = sb.append("--");sb = sb.append(BOUNDARY);sb = sb.append("\r\n");sb = sb.append("Content-Disposition: form-data; name=\"1\"; filename=\"1.txt\"\r\n");sb = sb.append("Content-Type: application/octet-stream\r\n\r\n");byte[] data = sb.toString().getBytes();byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();// 设置HTTP头:hc.setRequestProperty("Content-Type", MULTIPART_FORM_DATA + "; boundary=" + BOUNDARY);hc.setRequestProperty("Content-Length", String.valueOf(data.length + file.length + end_data.length));// 输出:output = hc.openOutputStream();output.write(data);output.write(file);output.write(end_data);// 读取服务器响应:// TODO...

 

 

参考:

转载请注明出处:

你可能感兴趣的文章
[转载]从100PV到1亿级PV网站架构演变
查看>>
StyleCop的常见错误
查看>>
谈谈随机数
查看>>
C# 3.0入门系列(三)
查看>>
.h头文件 .lib库文件 .dll动态库文件之间的关系
查看>>
联盟链和公有链混合架构如何实现?Hyperledger核心开发者陈昌访谈
查看>>
2017年,大数据工程师应该如何充实自己的专业工具箱
查看>>
《大秦帝国》作者孙皓晖将现身杭州华为阅读·DigiX读书会
查看>>
那个被大家用来用去的Ceph,终于成立了基金会
查看>>
“黑色”福利来袭 华为nova推潮流黑色系即将圣诞首发
查看>>
福建漳州大型新春花灯展亮灯
查看>>
香港海关破首宗流动厕所走私香烟案 案值约480万港元
查看>>
下沉市场“四大天王”受关注 水滴筹成健康保障领域独角兽
查看>>
寺库:打造独立平台塑造文化IP
查看>>
咸阳市警方侦破特大跨国网络传播淫秽物品案
查看>>
哈德森喜迎万分夜 CBA“第一外援”就此易主?
查看>>
荐书|Python编程之美:最佳实践指南,带你了解编程的美丽
查看>>
米6将取消3.5mm耳机插口,你还买吗?
查看>>
Rust Cargo使用总结
查看>>
【重温基础】9.正则表达式
查看>>