Servlet 3.0用标记方式实现的文件上传类

Servlet 3.0新特性提供了一些便利的配置,例如:web项目中不再需要web.xml.转用一些serlet的注解就可以实现原来的servlet配置功能。


下面的例子就是用标记来实现一个文件上传的servlet。运行环境,jdk1.7,Tomcat7

编译文件需要的第三方jar如下:commons-lang3-3.2.1.jar,commons-io-2.2.jar


代码如下:

UploadFileAction.java


==============================================================================

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * 上传文件测试 location为临时文件保存路径
 *
 * @author yongboy
 * @date 2011-1-13
 * @version 1.0
 */
@MultipartConfig(location = "D:/temp/", maxFileSize = 1024 * 1024 * 10)
@WebServlet("/upload")
public class UploadFileAction extends HttpServlet {
    

    // 得到注解信息
    private static final MultipartConfig config;

    static {
        config = UploadFileAction.class.getAnnotation(MultipartConfig.class);
    }

    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/upload.jsp").forward(request, response);
    }

    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        // 为避免获取文件名称时出现乱码
        request.setCharacterEncoding("UTF-8");

        Part part = null;
        try {
            // <input name="file" size="50" type="file" />
            part = request.getPart("file");
        } catch (IllegalStateException ise) {
            // 上传文件超过注解所标注的maxRequestSize或maxFileSize值
            if (config.maxRequestSize() == -1L) {
                System.out
                        .println("the Part in the request is larger than maxFileSize");
            } else if (config.maxFileSize() == -1L) {
                System.out
                        .println("the request body is larger than maxRequestSize");
            } else {
                System.out
                        .println("the request body is larger than maxRequestSize, or any Part in the request is larger than maxFileSize");
            }

            forwardErrorPage(request, response, "上传文件过大,请检查输入是否有误!");
            return;
        } catch (IOException ieo) {
            // 在接收数据时出现问题
            System.out
                    .println("I/O error occurred during the retrieval of the requested Part");
        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }

        if (part == null) {
            forwardErrorPage(request, response, "上传文件出现异常,请检查输入是否有误!");
            return;
        }

        // 得到文件的原始名称,eg :测试文档.pdf
        String fileName = getFileName(part);

        System.out.println("contentType : " + part.getContentType());
        System.out.println("fileName : " + fileName);
        System.out.println("fileSize : " + part.getSize());
        System.out.println("header names : ");
        for (String headerName : part.getHeaderNames()) {
            System.out.println(headerName + " : " + part.getHeader(headerName));
        }

        String saveName = System.currentTimeMillis() + "."
                + FilenameUtils.getExtension(fileName);

        System.out.println("save the file with new name : " + saveName);

        // 因在注解中指定了路径,这里可以指定要写入的文件名
        // 在未执行write方法之前,将会在注解指定location路径下生成一临时文件
        part.write(saveName);

        request.setAttribute("fileName", fileName);
        request.getRequestDispatcher("/uploadResult.jsp").forward(request,
                response);
    }

    private void forwardErrorPage(HttpServletRequest request,
            HttpServletResponse response, String errMsg)
            throws ServletException, IOException {
        request.setAttribute("errMsg", errMsg);

        request.getRequestDispatcher("/upload.jsp").forward(request, response);
    }

    /**
     * 如何得到上传的文件名, API没有提供直接的方法,只能从content-disposition属性中获取
     *
     * @param part
     * @return
     */
    protected static String getFileName(Part part) {
        if (part == null)
            return null;

        String fileName = part.getHeader("content-disposition");
        if (StringUtils.isBlank(fileName)) {
            return null;
        }

        return StringUtils.substringBetween(fileName, "filename=\"", "\"");
    }
}

=======================================================================

upload.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
</head>
<body>
<form name="form1" method="post" action="upload"  enctype="multipart/form-data">
<input name="param1" type="text" >
<input name="file" type="file" >

<input type="submit">
</form>
</body>
</html>

=======================================================================

uploadResult.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
</head>
<body>
上传成功!!!
</body>
</html>

=======================================================================

运行效果:


访问http://localhost:8080/ddd/upload.jsp地址


页面如下

1



2



3



4




可以看到文件成功上传到临时目录了。并且改名为数字文件编号


以下是这个标记需要注意的参数

需要熟悉MultipartConfig注解,标注在@WebServlet之上,具有以下属性:
属性名 类型 是否可选 描述
fileSizeThreshold int 当数据量大于该值时,内容将被写入文件。
location String 存放生成的文件地址。
maxFileSize long 允许上传的文件最大值。默认值为 -1,表示没有限制。
maxRequestSize long 针对该 multipart/form-data 请求的最大数量,默认值为 -1,表示没有限制。

一些实践建议:
  1. 若是上传一个文件,仅仅需要设置maxFileSize熟悉即可。
  2. 上传多个文件,可能需要设置maxRequestSize属性,设定一次上传数据的最大量。
  3. 上传过程中无论是单个文件超过maxFileSize值,或者上传总的数据量大于maxRequestSize值都会抛出IllegalStateException异常;
  4. location属性,既是保存路径(在写入的时候,可以忽略路径设定),又是上传过程中临时文件的保存路径,一旦执行Part.write方法之后,临时文件将被自动清除。
  5. 但Servlet 3.0规范同时也说明,不提供获取上传文件名的方法,尽管我们可以通过part.getHeader("content-disposition")方法间接获取得到。
  6. 如何读取MultipartConfig注解属性值,API没有提供直接读取的方法,只能手动获取。

猜你喜欢

转载自blog.csdn.net/rishengcsdn/article/details/53506701