`

multipart form-data boundary 说明

 
阅读更多
含义 ENCTYPE="multipart/form-data" 说明:
通过 http 协议上传文件 rfc1867协议概述,jsp 应用举例,客户端发送内容构造

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

2、上传文件的实例:用 servelet 实现(http server 为 tomcat 4.1.24)1. 在一个 html 网页中,写一个如下的form :

<formenctype="multipart/form-data"action="http://192.168.29.65/UploadFile"method=post>
loadmultifiles:<br>
<inputname="userfile1"type="file"><br>
<inputname="userfile2"type="file"><br>
<inputname="userfile3"type="file"><br><inputname="userfile4"type="file"><br>
textfield:<inputtype="text"name="text"value="text"><br>
<inputtype="submit"value="提交"><inputtype=reset></form>


用户可以选择多个文件,填写表单其它项,点击“提交”按钮后就开始上传给 http://192.168.29.65/upload_file/UploadFile

这是一个 servelet 程序注意 enctype="multipart/form-data", method=post, type="file" 。根据 rfc1867, 这三个属性是必须的。multipart/form-data 是新增的编码类型,以提高二进制文件的传输效率。具体的解释请参阅 rfc18672. 服务端 servelet 的编写现在第三方的 http upload file 工具库很多。Jarkata 项目本身就提供了fileupload 包http://jakarta.apache.org/commons/fileupload/ 。

文件上传、表单项处理、效率问题基 本上都考虑到了。在 Struts 中就使用了这个包,不过是用 Struts 的方式另行封装了一次。这里我们直接使用 fileupload 包。至于Struts 中的用法,请参阅 Struts 相关文档。这个处理文件上传的 servelet 主要代码如下:

publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
{
DiskFileUploaddiskFileUpload=newDiskFileUpload();//允许文件最大长度
diskFileUpload.setSizeMax(100*1024*1024);//设置内存缓冲大小
diskFileUpload.setSizeThreshold(4096);//设置临时目录
diskFileUpload.setRepositoryPath("c:/tmp");
ListfileItems=diskFileUpload.parseRequest(request);
Iteratoriter=fileItems.iterator();for(;iter.hasNext();)
{
FileItemfileItem=(FileItem)iter.next();
if(fileItem.isFormField()){//当前是一个表单项
out.println("formfield:"+fileItem.getFieldName()+","+fileItem.getString());
}else{
//当前是一个上传的文件
StringfileName=fileItem.getName();
fileItem.write(newFile("c:/uploads/"+fileName));
}

}}


为简略起见,异常处理,文件重命名等细节没有写出。3、 客户端发送内容构造假设接受文件的网页程序位于 http://192.168.29.65/upload_file/UploadFile.假设我们要发送一个二进制文件、一个文本框表单项、一个密码 框表单项。文件名为 E:/s ,其内容如下:(其中的XXX代表二进制数据,如 01 02 03)abbXXXccc 客户端应该向 192.168.29.65 发送如下内容:



POST/upload_file/UploadFileHTTP/1.1
Accept:text/plain,*/*
Accept-Language:zh-cn
Host:192.168.29.65:80
Content-Type:multipart/form-data;boundary=---------------------------7d33a816d302b6
User-Agent:Mozilla/4.0(compatible;OpenOffice.org)
Content-Length:424
Connection:Keep-Alive-----------------------------7d33a816d302b6
Content-Disposition:form-data;
name="userfile1";
filename="E:/s"Content-Type:
application/octet-streamabbXXXccc
-----------------------------7d33a816d302b6

Content-Disposition:form-data;

name="text1"foo

-----------------------------7d33a816d302b6

Content-Disposition:form-data;

name="password1"bar

-----------------------------7d33a816d302b6--

(上面有一个回车)此内容必须一字不差,包括最后的回车。

注意:Content-Length: 424 这里的424是红色内容的总长度(包括最后的回车)
注意这一行:Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6

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

其中33a816d302b6 是即时生成的一个数字,用以确保整个分隔符不会在文件或表单项的内容中出现。前面的 ---------------------------7d 是 IE 特有的标志。

Mozila 为---------------------------71用手工发送这个例子,在上述的 servlet 中检验通过。




使用POST发送数据

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

POSThttp://127.0.0.1/login.doHTTP/1.0
Accept:image/gif,image/jpeg,image/pjpeg,*/*
Accept-Language:en-us,zh-cn;q=0.5
Content-Type:application/x-www-form-urlencoded
User-Agent:Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1)
Content-Length:28
/r/n
username=admin&password=1234


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

hc.setRequestMethod(HttpConnection.POST);


  然后构造出HTTP正文:

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

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

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

  然后打开OutputStream将正文写入:

OutputStreamoutput=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:

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

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

--ABCD
Content-Disposition:form-data;name="title"
/r/n
Today
--ABCD
Content-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=...//文件内容
StringBOUNDARY="---------------------------7d4a6d158c9";//分隔符
StringBuffersb=newStringBuffer();
//发送每个字段:
for(inti=0;i
sb=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...

分享到:
评论

相关推荐

    Python发送form-data请求及拼接form-data内容的方法

    网上关于使用python 的发送multipart/form-data的方法,多半是采用 ulrlib2 的模拟post方法,如下: import urllib2\nboundary='-------------------------7df3069603d6' data=[] data.append('--%s' % boundary) ...

    python处理multipart/form-data的请求方法

    今天小编就为大家分享一篇python处理multipart/form-data的请求方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    http/formdata

    multipart/form-data的数据由多个part组成,part间通过boundary分隔符进行分割,每个part由header和content组成 multipart/form-data的格式大致为: ----------------------------904587217962624105581666 ...

    form-data-body:一个微小的,无依赖的节点模块,用于为POST请求生成表单的multipartform-data主体

    一个很小的,无依赖的节点模块,用于为POST请求生成表单的multipart / form-data主体。 这意味着它是一个简单的,没有多余的装饰的模块,用于生成要作为POST请求的主体发送的字符串,以模拟表单提交。 如果您需要...

    C#使用HttpListener实现异步监听的demo

    HttpListener、HttpWebRequest的应用,包括如何解析POST请求中Body的数据(multipart/form-data)、如何构造multipart/form-data; boundary=的ContentType等技巧

    webbench-plus-post:这是一个基于webbench-1.5的项目。 添加了POST方法,支持applicationx-www-form-data-urlencoded和rfc1867,并且用户可以指定多个HTTP标头

    webbench加上帖子 ... 2.Content-Type:multipart / form-data; boundary = random_bytes_or_numbers webbench --post文件名--file --header header1:value1 --header header2:value2 -t time -c数字

    vccustombr

    而post图片则是自己构造http协议数据,将http协议头的Content-Type设为multipart/form-data,同时还要加上 boundary=xxxxxxx(xxxxxxx表示一个字符串),后面的协议数据内容将要以这个xxxxxxx来进行分隔。...

    MFC UploadPhoto实例加源码.rar

    而post图片则是自己构造http协议数据,将http协议头的Content-Type设为multipart/form-data,同时还要加上 boundary=xxxxxxx(xxxxxxx表示一个字符串),后面的协议数据内容将要以这个xxxxxxx来进行分隔。...

    java 编写文件上传类简单易用

    form action="/servlet/ReceiveServlet" ENCTYPE="multipart/form-data" method=post &gt; C)提交请求 提交请求的过程由浏览器完成的,并且遵循 HTTP 协议,每一个从浏览器端到服务器端的一个请求,都包含了...

    带进度传上传文件

    带进度条上传代码,适合学习参考资料,也可直接使用到项目中. 代码片段: Private Sub Class_Initialize() Set Files = Server.... Exit Sub ''如果form中没有包括multipart/form-data上传是无效的 End If

    微信企业号项目

    //conn.setRequestProperty("Content-Type","multipart/form-data;"); //设置边界 String BOUNDARY = "----------" + System.currentTimeMillis(); conn.setRequestProperty("Content-Type","multipart/form-...

    IHTTPModel接口实现文件上传

    m_contentType.StartsWith("multipart/form-data", StringComparison.OrdinalIgnoreCase)) return; if (!m_workRequest.HasEntityBody()) return; #endregion #region 获取分隔符 string m_boundaryStr = m_...

    mongodb_cache_system

    mongodb_cache_system 获取所有缓存-端点-/ api / v1 /... PUT缓存-{方法:'PUT',网址:'/ api / v1 / cache /',标头:{'content-type':'multipart / form-data; boundary = ---- WebKitFormBoundary7MA4YWxkTrZu0g

    HTTP content-type

    Content-Type(内容类型),一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定...Content-Type: multipart/form-data; boundary=something 实例: 常见的媒体格式类型如下: text/ht

    先锋无组件上传类(无惧2.0杜绝上传漏洞修改版) v2004

    Content-Type: multipart/form-data; boundary=---------------------------7d423a138d0278 Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)...

    p6-HTTP-MultiPartParser:Perl6的多部分数据解析器

    名称 ...概要 ... ... boundary =&gt; $boundary, on_header =&gt; $on_header, ...HTTP :: MultiPartParser是低级的multipart / form-data解析器库。 该库是chansen用于Perl5的HTTP :: MultiPartParser的端口。 方法 新的 $parser

    Android 上传文件工具类

    String CONTENT_TYPE = "multipart/form-data"; // 内容类型 try { URL url = new URL(RequestURL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(TIME_...

    Python request post上传文件常见要点

    通用用法 但上图的字段名,类型需要根据不同接口... # Content-Type: multipart/form-data; boundary=alamofire.boundary.3c7024a080e6a27f, #注意,此处不要写Content-Type apiVersion: v1.0.0, appVersion: v1.0.0,

    ios开发小技巧

    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data;boundary=%@",boundary]; [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; // NSMutableData *body = ...

Global site tag (gtag.js) - Google Analytics