网站首页 > 网管员之家  > 网页设计 > 当前主题    站内搜索    首页  上一页  下一页  尾页  页次1/1         新用户申请  老用户登录  返回首页
作者信息   主题: 文件上传的实现的关键:enctype="multipart/form-data"3073

admin


发表主题: 891
发表回复: 1979
网站暂行积分: 4652


【人类幸存者】



  发表时间: 2008-7-15 16:19:31             


今天想知道文件上传的原理,搜索了半天终于找到了一篇实用的文章.
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

并按该文章实现了文件的上传功能.
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

通过 http 协议上传文件
浪漫烛光 www.langmanzg.com

                 rfc1867协议概述,jsp 应用举例,客户端发送内容构造
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

1、概述
浪漫烛光 www.langmanzg.com

在最初的 http 协议中,没有上传文件方面的功能。 rfc1867 (http://www.ietf.org/rfc/rfc1867.txt) 为 http 协议添加了这个功能。客户端的浏览器,如 Microsoft IE, Mozila, Opera 等,按照此规范将用户指定的文件发送到服务器。服务器端的网页程序,如 php, asp, jsp 等,可以按照此规范,解析出用户发送来的文件。
浪漫烛光 www.langmanzg.com

Microsoft IE, Mozila, Opera 已经支持此协议,在网页中使用一个特殊的 form 就可以发送文件。
浪漫烛光 www.langmanzg.com

绝大部分 http server ,包括 tomcat ,已经支持此协议,可接受发送来的文件。
浪漫烛光 www.langmanzg.com

各种网页程序,如 php, asp, jsp 中,对于上传文件已经做了很好的封装。
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

2、上传文件的实例:用 servelet 实现(http server 为 tomcat 4.1.24)
浪漫烛光 www.langmanzg.com

1. 在一个 html 网页中,写一个如下的form :
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

用户可以选择多个文件,填写表单其它项,点击“提交”按钮后就开始上传给 http://192.168.29.65/upload_file/UploadFile 这是一个 servelet 程序
浪漫烛光 www.langmanzg.com

注意 enctype="multipart/form-data", method=post, type="file" 。根据 rfc1867, 这三个属性是必须的。multipart/form-data 是新增的编码类型,以提高二进制文件的传输效率。具体的解释请参阅 rfc1867
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

2. 服务端 servelet 的编写
浪漫烛光 www.langmanzg.com

现在第三方的 http upload file 工具库很多。Jarkata 项目本身就提供了fileupload 包http://jakarta.apache.org/commons/fileupload/ 。文件上传、表单项处理、效率问题基本上都考虑到了。在 struts 中就使用了这个包,不过是用 struts 的方式另行封装了一次。这里我们直接使用 fileupload 包。至于struts 中的用法,请参阅 struts 相关文档。
浪漫烛光 www.langmanzg.com

这个处理文件上传的 servelet 主要代码如下:
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

需要导入的包如下:
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

import org.apache.commons.fileupload.DiskFileUpload;
浪漫烛光 www.langmanzg.com

import org.apache.commons.fileupload.FileItem;
浪漫烛光 www.langmanzg.com

import org.apache.commons.fileupload.FileUploadException;
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

(以上的包可在spring-framework-2.0.5\lib\jakarta-commons\commons-fileupload.jar中找到)
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

public void doPost( HttpServletRequest request, HttpServletResponse response ) {
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    DiskFileUpload diskFileUpload = new DiskFileUpload();
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    // 允许文件最大长度
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    diskFileUpload.setSizeMax( 100*1024*1024 );
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    // 设置内存缓冲大小
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    diskFileUpload.setSizeThreshold( 4096 );
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    // 设置临时目录
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    diskFileUpload.setRepositoryPath( "c:/tmp" );
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    List fileItems = diskFileUpload.parseRequest( request );
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    Iterator iter = fileItems.iterator();
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    for( ; iter.hasNext(); ) {
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

        FileItem fileItem = (FileItem) iter.next();
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

        if( fileItem.isFormField() ) {
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

            // 当前是一个表单项
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

            out.println( "form field : " + fileItem.getFieldName() + ", " + fileItem.getString() );
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

        } else {
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

            // 当前是一个上传的文件
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

            String fileName = fileItem.getName();
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

            fileItem.write( new File("c:/uploads/"+fileName) );
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

        }
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

    }
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

}
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

为简略起见,异常处理,文件重命名等细节没有写出。
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

3、 客户端发送内容构造
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

假设接受文件的网页程序位于 http://192.168.29.65/upload_file/UploadFile.
浪漫烛光 www.langmanzg.com

假设我们要发送一个二进制文件、一个文本框表单项、一个密码框表单项。文件名为 E:\s ,其内容如下:(其中的XXX代表二进制数据,如 01 02 03)
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

a
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

bb
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

XXX
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

ccc
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

jNiStdcD"e;^1[9C户端应该向 192.168.29.65 发送如下内容:
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

POST /upload_file/UploadFile HTTP/1.1
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

Accept: text/plain, */*
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

Accept-Language: zh-cn
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

Host: 192.168.29.65:80
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

Content-Type:multipart/form-data;boundary=---------------------------7d33a816d302b6
浪漫烛光 www.langmanzg.com

User-Agent: Mozilla/4.0 (compatible; OpenOffice.org)
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

Content-Length: 424
浪漫烛光 www.langmanzg.com

Connection: Keep-Alive
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

-----------------------------7d33a816d302b6
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

Content-Disposition: form-data; name="userfile1"; filename="E:\s"
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

Content-Type: application/octet-stream
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

a
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

bb
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

XXX
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

ccc
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

-----------------------------7d33a816d302b6
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

Content-Disposition: form-data; name="text1"
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

foo
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

-----------------------------7d33a816d302b6
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

Content-Disposition: form-data; name="password1"
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

bar
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

-----------------------------7d33a816d302b6--
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

(上面有一个回车)
浪漫烛光 www.langmanzg.com


浪漫烛光 www.langmanzg.com

此内容必须一字不差,包括最后的回车。
浪漫烛光 www.langmanzg.com

注意:Content-Length: 424 这里的424是红色内容的总长度(包括最后的回车)
浪漫烛光 www.langmanzg.com

注意这一行:
浪漫烛光 www.langmanzg.com

Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6
浪漫烛光 www.langmanzg.com

根据 rfc1867, multipart/form-data是必须的.
浪漫烛光 www.langmanzg.com

---------------------------7d33a816d302b6 是分隔符,分隔多个文件、表单项。其中33a816d302b6 是即时生成的一个数字,用以确保整个分隔符不会在文件或表单项的内容中出现。前面的 ---------------------------7d 是 IE 特有的标志。 Mozila 为---------------------------71
浪漫烛光 www.langmanzg.com

用手工发送这个例子,在上述的 servlet 中检验通过。
浪漫烛光 www.langmanzg.com





  不要再悲叹哀怨,切莫再有泪空弹。 用鲜花洗涤旧世,剑之锋血光闪闪。
新用户注册   返回首页
首页  上一页  下一页  尾页  页次1/1   转到第