Servlet 文件上传

Servlet 可以与 HTML form 标签一起使用,来允许用户上传文件到服务器。上传的文件可以是文本文件或图像文件或任何文档。

本文使用到的文件有:

  • upload.jsp : 文件上传表单。
  • message.jsp : 上传成功后跳转页面。
  • UploadServlet.java : 上传处理 Servlet。
  • 需要引入的 jar 文件:commons-fileupload-1.3.2、commons-io-2.5.jar。

创建一个文件上传表单

下面的 HTML 代码创建了一个文件上传表单。以下几点需要注意:

  • 表单 method 属性应该设置为 POST 方法,不能使用 GET 方法。
  • 表单 enctype 属性应该设置为 multipart/form-data.
  • 表单 action 属性应该设置为在后端服务器上处理文件上传的 Servlet 文件。
  • 上传单个文件,您应该使用单个带有属性 type="file" 的 <input .../> 标签。为了允许多个文件上传,请包含多个 name 属性值不同的 input 标签。输入标签具有不同的名称属性的值。浏览器会为每个 input 标签关联一个浏览按钮。

upload.jsp 文件代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="upload" method="post" enctype="multipart/form-data">
    <table align="center" border="1">
        <caption>Servlet文件上传</caption>
        <tbody>
        <tr>
            <td><label>用户名:</label></td>
            <td><input type="text" name="username" placeholder="用户名"></td>
        </tr>
        <tr>
            <td><label>密码</label></td><td>
                <input type="password" name="password" placeholder="密码">
            </td>
        </tr>
        <tr>
            <td colspan="2"><input name="file" type="file"></td>
        </tr>
        <tr>
            <td colspan="2" align="center"><input type="submit" value="提交"></td>
        </tr>
        </tbody>
    </table>
</form>
</body>
</html>

 编写后台Servlet

UploadServlet 的源代码 如下所示:

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.FileCleanerCleanup;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileCleaningTracker;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@WebServlet(name = "UploadServlet", urlPatterns = {"/upload"})
public class UploadServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (!ServletFileUpload.isMultipartContent(request)) {
            PrintWriter writer = response.getWriter();
            response.getWriter().println("Error: 表单必须包含 enctype=multipart/form-data");
            writer.flush();
        } else {
            int sizeThreshold = 10 * 1024;// 上传文件的阈值, 单位字节
            long fileSizeMax = 10485760;// 上传文件的最大字节数
            String realPath = getServletContext().getRealPath("/");// 获取应用在服务器根路径下的真实路径
            System.out.println("contextPath: " + realPath);
            File saveDir = new File(realPath + "/resources");// 上传的文件保存的文件夹
            File tempDir = new File(realPath + "/temp");// 上传的临时文件存储文件夹
            DiskFileItemFactory factory = new DiskFileItemFactory();// 创建磁盘文件下载工厂处理类
            factory.setSizeThreshold(sizeThreshold);// 设置文件直接写入磁盘的大小阈值。如果上传文件超过这个值,则会产生上传临时文件,保存在临时文件上
            if (!tempDir.exists()) {
                // 如果临时文件缓存文件夹不存在,则创建一个文件夹
                tempDir.mkdirs();
            }
            factory.setRepository(tempDir);//设置临时文件保存目录

            FileCleaningTracker tracker = FileCleanerCleanup.getFileCleaningTracker(request.getServletContext());// 文件清除追踪器
            factory.setFileCleaningTracker(tracker);// 设置文件清除追踪器
            ServletFileUpload fileUpload = new ServletFileUpload(factory);// 创建文件上传Servlet处理类
            fileUpload.setHeaderEncoding("UTF-8");// 设置字符编码
            fileUpload.setProgressListener(new ProgressListener() {
                public void update(long pBytesRead, long pContentLength, int pItems) {
                    // pBytesRead:已经读到的字节数
                    // pContentLength:正在读取的文件的总字节总数。如果这个数字是未知的,可能是-1,
                    // pItems:当前正在读取的在页面第几项。(0 =目前没有读取项,1 =第一项正在阅读,…)
                    System.out.println("pBytesRead:" + pBytesRead + ", pContentLength:" + pContentLength + ", pItems:" + pItems);
                }
            });// 设置文件上传进度监听器
            fileUpload.setFileSizeMax(fileSizeMax);// 设置文件上传的最大字节数,我这里设置为10M
            // 设置最大允许一个完整的请求的大小,而不是setFileSizeMax()。
            // 允许的最大大小,以字节为单位。默认值- 1表示没有限制。
            //fileUpload.setSizeMax(fileSizeMax);
            try {
                List<FileItem> fileItems = fileUpload.parseRequest(request);
                Iterator<FileItem> iterator = fileItems.iterator();
                while (iterator.hasNext()) {
                    FileItem fileItem = iterator.next();
                    if (fileItem.isFormField()) {
                        // 如果是表单数据
                        String fieldName = fileItem.getFieldName();
                        String value = fileItem.getString("UTF-8");
                        System.out.println("fieldName:" + fieldName + ", value:" + value);
                    } else {
                        // 如果是上传文件数据
                        if (fileItem.getSize() > 0) {
                            // 文件大小大于0
                            String name = fileItem.getName();// 返回客户端文件系统中的原始文件名,由浏览器(或其他客户端软件)提供。
                            // 有可能包含路径,所以这里进行处理
                            String fileName = FilenameUtils.getName(name);// 通过Common io提供的工具类,获取文件名
                            // 通过FileUtils提供的工具方法进行文件保存操作
                            FileUtils.copyInputStreamToFile(fileItem.getInputStream(), new File(saveDir, fileName));
                        }
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
        }
    }
}

 

运行项目,查看结果

在浏览器地址打开:http://localhost:8080/web/upload.jsp,出现下图页面。

输入表单内容,点击提交按钮后,在控制台出现如下结果

contextPath: C:\Users\Administrator\IdeaProjects\web\target\web\
pBytesRead:4096, pContentLength:763062, pItems:0
pBytesRead:4096, pContentLength:763062, pItems:1
pBytesRead:4096, pContentLength:763062, pItems:2
pBytesRead:4096, pContentLength:763062, pItems:3

...... 此处省略多行

pBytesRead:761772, pContentLength:763062, pItems:3
pBytesRead:761856, pContentLength:763062, pItems:3
pBytesRead:763062, pContentLength:763062, pItems:3
fieldName:username, value:scott
fieldName:password, value:tiger 

 

 大功告成,如果有什么问题,欢迎指正。

posted @ 2017-06-13 11:11  追寻拉夫特尔  阅读(168)  评论(0编辑  收藏  举报