# 文件上传

重点

# 一、简介

在项目中,文件的上传是常见的功能。很多程序或者软件中都经常使用到文件的上传。

  • 邮箱中有附件的上传;
  • 图片上传。

# 二、什么是文件上传

当用户在前端页面点击文件上传后,用户上传的文件数据提交给服务器端,实现保存。

# 三、上传的相关限制

# 3.1、上传对表单的限制

  • method="post"
  • enctype="multipart/form-data"
  • 表单中需要添加文件表单项:<input type="file" name="xxx" />
<form action="xxx" method="post" enctype="multipart/form-data">
  用户名;<input type="text" name="username"/><br/>
  照 片:<input type="file" name="photo"/><br/>
  <input type="submit" value="上传"/>
</form>
1
2
3
4
5

# 3.2、上传对Servlet的限制

request.getParameter("xxx")这个方法在表单为enctype="multipart/form-data"时,它作废了,它永远都返回null

# 3.3、如何实现文件上传

# 3.3.1、相关Jar包

  • commons-fileupload-1.4.jar
  • commons-io-2.2.jar

它会帮我们解析request中的上传数据,解析后的结果是一个表单项数据封装到一个FileItem对象中。我们只需要调用FileItem的方法即可。

# 3.3.2、具体步骤

  1. 创建工厂:DiskFileItemFactory factory = new DiskFileItemFactory()

  2. 创建解析器:ServletFileUpload sfu = new ServletFileUpload(factory)

  3. 使用解析器来解析request,得到FileItem集合:

    List<FileItem> fileItemList = sfu.parseRequest(request)

    FileItem中常用方法:

    • boolean isFormField():是否为普通表单项!返回true为普通表单项,如果为false即文件表单项
    • String getFieldName():返回当前表单项的名称
    • String getString(String charset):返回表单项的值
    • String getName():返回上传的文件名称;
    • long getSize():返回上传文件的字节数;
    • InputStream getInputStream():返回上传文件对应的输入流;
    • void write(File destFile):把上传的文件内容保存到指定的文件中。
//1 创建工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2 创建解析器
ServletFileUpload sfu = new ServletFileUpload(factory);
//使用解析器ServletFileUpload.parseRequest() 来解析request,得到FileItem集合

try {
    List<FileItem> list = sfu.parseRequest(request);
    for (FileItem item : list) {
        if(item.isFormField()) {
            String fieldName = item.getFieldName();
            String value = item.getString("utf-8");
            System.out.println(fieldName + ":" + value);
        } else {
            String fileName = item.getName();
            long size = item.getSize();
            System.out.println("文件名:" + fileName);
            System.out.println("文件大小" + size);
            
            ServletContext servletContext = this.getServletConfig().getServletContext();
            String realPath = servletContext.getRealPath("/img");
            
            item.write(new File(realPath + "/" + fileName));
        }
    }
} catch (FileUploadException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}
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

文件上传步骤: 1 导包 2 在web下建file目录,可以建一个空文件,避免file目录不能打包的问题 3 建jsp,注意 method="post" enctype= "multipart/form-data" 4 建servlet,重写doPost方法

# 3.4、需要注意的细节

# 3.4.1、文件名或普通表单项乱码

如何解决:

  • request.setCharacterEncoding("utf-8");
  • servletFileUpload.setHeaderEncoding("utf-8");

以上两个方案二选一

//创建工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建解析器
ServletFileUpload sfu = new ServletFileUpload(factory);
request.setCharacterEncoding("utf-8");
//sfu.setHeaderEncoding("utf-8");

try {
    //使用解析器来解析request,得到FileItem集合
    List<FileItem> list = sfu.parseRequest(request);
    for (FileItem item : list) {
        if(item.isFormField()) {
            String fieldName = item.getFieldName();
            String value = item.getString("utf-8");
            System.out.println(fieldName + ":" + value);
        } else {
            String fileName = item.getName();
            long size = item.getSize();
            System.out.println("文件名:" + fileName);
            System.out.println("文件大小" + size);
            
            ServletContext servletContext = this.getServletConfig().getServletContext();
            String realPath = servletContext.getRealPath("/img");
            
            item.write(new File(realPath + "/" + fileName));
        }
    }
} catch (FileUploadException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}
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

# 3.4.2、同名文件上传问题

使用UUID:fileName = UUID.randomUUID().toString();

//创建工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建解析器
ServletFileUpload sfu = new ServletFileUpload(factory);
request.setCharacterEncoding("utf-8");
//sfu.setHeaderEncoding("utf-8");

try {
    //使用解析器来解析request,得到FileItem集合
    List<FileItem> list = sfu.parseRequest(request);
    for (FileItem item : list) {
        if(item.isFormField()) {
            String fieldName = item.getFieldName();
            String value = item.getString("utf-8");
            System.out.println(fieldName + ":" + value);
        } else {
            String fileName = item.getName();
            long size = item.getSize();
            System.out.println("文件名:" + fileName);
            System.out.println("文件大小" + size);
            
            ServletContext servletContext = this.getServletConfig().getServletContext();
            String realPath = servletContext.getRealPath("/img");
            
            item.write(new File(realPath + 
                                "/" + 
                                UUID.randomUUID().toString().replace("-", "") + 
                                "_" + 
                                fileName));
        }
    }
} catch (FileUploadException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}
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
上次更新: 2024/4/13