JavaWeb之上传文件

JavaWeb之上传文件

一、文件上传对页面的要求

1,必须使用表单

2,表单的method必须是POST,而不是GET

3,表单的enctype必须是multipart/form-data;

4,在表单中添加file表单字段,即<input type=”file”…/>

即:

 HTML Code 
1
2
3
4
5
6
7
     <form   action = "${pageContext.request.contextPath }/FileUploadServlet"   method = "post"   enctype = "multipart/form-data" >
        用户名:
<input   type = "text"   name = "username" /><br/>
        文件1:
<input   type = "file"   name = "file1" /><br/>
        文件2:
<input   type = "file"   name = "file2" /><br/>
        
<input   type = "submit"   value = "提交" />
    
</form>

二、对比文件上传表单和普通文本表单的区别

l  文件上传表单的enctype=”multipart/form-data”,表示多部件表单数据;

l  普通文本表单可以不设置enctype属性:

扫描二维码关注公众号,回复: 39841 查看本文章

Ø  当method=”post”时,enctype的默认值为application/x-www-form-urlencoded,表示使用url编码正文;

当method=”get”时,enctype的默认值为null,没有正文,所以就不需要enctype了。

三、文件上传表单的测试

 HTML Code 
1
2
3
4
5
6
7
<form   action = "${pageContext.request.contextPath }/FileUploadServlet"   method = "post"   enctype = "multipart/form-data" >
        用户名:
<input   type = "text"   name = "username" /><br/>
        文件1:
<input   type = "file"   name = "file1" /><br/>
        文件2:
<input   type = "file"   name = "file2" /><br/>
        
<input   type = "submit"   value = "提交" />
    
</form>


通过测试,查看表单请求数据正文部分,发现正文部分是由多个部件组成,每个部件对应一个表单字段,每个部件都有自己的头信息。头信息下面是空行,空行下面是字段的正文部分。多个部件之间使用随机生成的分隔线隔开。

文本字段的头信息中只包含一条头信息,即Content-Disposition,这个头信息的值有两个部分,第一部分是固定的,即form-data,第二部分为字段的名称。在空行后面就是正文部分了,正文部分就是在文本框中填写的内容。

  文件字段的头信息中包含两条头信息,Content-Disposition和Content-Type。Content-Disposition中多出一个filename,它指定的是上传的文件名称。而Content-Type指定的是上传文件的类型。文件字段的正文部分就是文件的内容。 

四、文件上传对Servlet的要求

首先我们要肯定一点,文件上传表单的数据也是被封装到request对象中的。

request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。

这时可以使用request的getInputStream()方法获取ServletInputStream对象,它是InputStream的子类,这个ServletInputStream对象对应整个表单的正文部分(从第一个分隔线开始,到最后),这说明我们需要的解析流中的数据。当然解析它是很麻烦的一件事情,而Apache已经帮我们提供了解析它的工具:commons-fileupload。

五、commons-fileupload介绍

为什么使用fileupload:

上传文件的要求比较多,需要记一下:

l  必须是POST表单;

l  表单的enctype必须是multipart/form-data;

l  在表单中添加file表单字段,即<input type=”file”…/>

Servlet的要求:

l  不能再使用request.getParameter()来获取表单数据;

l  可以使用request.getInputStream()得到所有的表单数据,而不是一个表单项的数据;

l  这说明不使用fileupload,我们需要自己来对request.getInputStream()的内容进行解析!!!

1,fileupload概述

fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()。

fileupload组件需要的JAR包有:

l  commons-fileupload.jar,核心包;

l  commons-io.jar,依赖包。

2,fileupload简单应用

fileupload的核心类有:DiskFileItemFactory,ServletFileUpload,FileItem

使用步骤如下:

1.      创建工厂类DiskFileItemFactory对象:DiskFileItemFactoryfactory = new DiskFileItemFactory()

2.      使用工厂创建解析器对象:ServletFileUpload fileUpload = new ServletFileUpload(factory)

3.      使用解析器来解析request对象:List<FileItem>list = fileUpload.parseRequest(request)

介绍FileItem类,它才是我们最终要的结果。一个FileItem对象对应一个表单项(表单字段)。一个表单中存在文件字段和普通字段,可以使用FileItem类的isFormField()方法来判断表单字段是否为普通字段,如果不是普通字段,那么就是文件字段了。

l  String getName():获取文件字段的文件名称;

l  String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;

l  String getFieldName():获取字段名称,例如:<inputtype=”text” name=”username”/>,返回的是username;

l  String getContentType():获取上传的文件的类型,例如:text/plain。

l  int getSize():获取上传文件的大小;

l  boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;

l  InputStream getInputStream():获取上传文件对应的输入流;

l  void write(File):把上传的文件保存到指定文件中。

六、简单上传示例

第一步:

完成index.jsp,只需要一个表单。注意表单必须是post的,而且enctype必须是mulitpart/form-data的。

 HTML Code 
1
2
3
4
5
6
  <form   action = "${pageContext.request.contextPath }/FileUploadServlet"   method = "post"   enctype = "multipart/form-data" >
        用户名:
<input   type = "text"   name = "username" /><br/>
        文件1:
<input   type = "file"   name = "file1" /><br/>
        
<input   type = "submit"   value = "提交" />
    
</form>

第二步:

完成FileUploadServlet

 HTML Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
         //  因为要使用response打印,所以设置其编码
        response.setContentType(
"text/html;charset=utf-8" );
        
        
//  创建工厂
        DiskFileItemFactory dfif = new DiskFileItemFactory();
        
//  使用工厂创建解析器对象
        ServletFileUpload fileUpload = new ServletFileUpload(dfif);
        try {
            
//  使用解析器对象解析request,得到FileItem列表
            List
< FileItem >  list = fileUpload.parseRequest(request);
            
//  遍历所有表单项
            for(FileItem fileItem : list) {
                
//  如果当前表单项为普通表单项
                if(fileItem.isFormField()) {
                    
//  获取当前表单项的字段名称
                    String fieldName = fileItem.getFieldName();
                    
//  如果当前表单项的字段名为username
                    if(fieldName.equals(
"username" )) {
                        
//  打印当前表单项的内容,即用户在username表单项中输入的内容
                        response.getWriter().print(
"用户名:"  + fileItem.getString() +  "<br/>" );
                    }
                } else {
// 如果当前表单项不是普通表单项,说明就是文件字段
                    String name = fileItem.getName();
// 获取上传文件的名称
                    
//  如果上传的文件名称为空,即没有指定上传文件
                    if(name == null || name.isEmpty()) {
                        continue;
                    }
                    
//  获取真实路径,对应${项目目录} / uploads,当然,这个目录必须存在
                    String savepath = this.getServletContext().getRealPath(
"/uploads" );
                    
//  通过uploads目录和文件名称来创建File对象
                    File file = new File(savepath, name);
                    
//  把上传文件保存到指定位置
                    fileItem.write(file);
                    
//  打印上传文件的名称
                    response.getWriter().print(
"上传文件名:"  + name +  "<br/>" );
                    
//  打印上传文件的大小
                    response.getWriter().print(
"上传文件大小:"  + fileItem.getSize() +  "<br/>" );
                    
//  打印上传文件的类型
                    response.getWriter().print(
"上传文件类型:"  + fileItem.getContentType() +  "<br/>" );
                }
            }
        } catch (Exception e) {
            throw new ServletException(e);
        } 
    }

















猜你喜欢

转载自blog.csdn.net/king_cannon_fodder/article/details/80022958