java servlet 3.0文件上传

在以前,处理文件上传是一个很痛苦的事情,大都借助于开源的上传组件,诸如commons fileupload等。现在好了,很方便,便捷到比那些组件都方便至极。以前的HTML端上传表单不用改变什么,还是一样的multipart/form-data MIME类型。

让Servlet支持上传,需要做两件事情

  1. 需要添加MultipartConfig注解
  2. 从request对象中获取Part文件对象

但在具体实践中,还是有一些细节处理,诸如设置上传文件的最大值,上传文件的保存路径。

需要熟悉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没有提供直接读取的方法,只能手动获取。

来一个示例吧,上传前台页面:

后台处理Servlet:

/** * 上传文件测试 location为临时文件保存路径 *  */@MultipartConfig(location = "/tmp", maxFileSize = 1024 * 1024 * 10)@WebServlet("/upload")public class UploadFileAction extends HttpServlet { private static final long serialVersionUID = 92166165626L; private static final Log log = LogFactory.getLog(UploadFileAction.class); // 得到注解信息 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) {    log.info("the Part in the request is larger than maxFileSize");   } else if (config.maxFileSize() == -1L) {    log.info("the request body is larger than maxRequestSize");   } else {    log.info("the request body is larger than maxRequestSize, or any Part in the request is larger than maxFileSize");   }

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

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

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

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

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

  log.info("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=\"", "\""); }

文件上传成功之后,以及日志输出的截图如下:

截图中可以看到Part包含content-disposition属性,可以很容易从值中抽取出文件名。临时生成的上传文件大都以 .tmp为后缀,大致如下:

让上传出现错误,就可以在保存路径下看到大致如上的临时文件。

一次上传多个文件的后台servlet示范:

/** * 多文件上传支持 * @author yongboy * @date 2011-1-14 * @version 1.0 */@MultipartConfig(  location = "/home/yongboy/tmp/",   maxFileSize = 1024L * 1024L, // 每一个文件的最大值  maxRequestSize = 1024L * 1024L * 10L // 一次上传最大值,若每次只能上传一个文件,则设置maxRequestSize意义不大)@WebServlet("/uploadFiles")public class UploadFilesAction extends HttpServlet { private static final long serialVersionUID = 2304820820384L; private static final Log log = LogFactory.getLog(UploadFilesAction.class);

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

 protected void doPost(HttpServletRequest request,   HttpServletResponse response) throws ServletException, IOException {  request.setCharacterEncoding("UTF-8");

  Collection parts = null;  try {   parts = request.getParts();  } catch (IllegalStateException ise) {   // 可能某个文件大于指定文件容量maxFileSize,或者提交数据大于maxRequestSize   log.info("maybe the request body is larger than maxRequestSize, or any Part in the request is larger than maxFileSize");  } catch (IOException ioe) {   // 在获取某个文件时遇到拉IO异常错误   log.error("an I/O error occurred during the retrieval of the Part components of this request");  } catch (Exception e) {   log.error("the request body is larger than maxRequestSize, or any Part in the request is larger than maxFileSize");   e.printStackTrace();  }

  if (parts == null || parts.isEmpty()) {   doError(request, response, "上传文件为空!");   return;  }

  // 前端具有几个file组件,这里会对应几个Part对象  List fileNames = new ArrayList();  for (Part part : parts) {   if (part == null) {    continue;   }   // 这里直接以源文件名保存   String fileName = UploadUtils.getFileName(part);

   if (StringUtils.isBlank(fileName)) {    continue;   }

   part.write(fileName);   fileNames.add(fileName);  }

  request.setAttribute("fileNames", fileNames);  request.getRequestDispatcher("/uploadsResult.jsp").forward(request,    response); }

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

  this.doGet(request, response); }}

批量上传很简单,但也有风险,任一个文件若超过maxFileSize值,意味着整个上传都会失败。若不限大小,那就不存在以上忧虑了。

总之,在Servlet 3.0 中,无论是上传一个文件,或者多个批量上传都是非常简单,但要处理好异常,避免出错。

时间: 2024-10-10 03:07:36

java servlet 3.0文件上传的相关文章

jsp Servlet 3.0文件上传

Servlet 3.0之前上传文件一般都要借助与第三方插件上传,有了servlet3.0后,上传文件从此变得简单.老规矩,直接上代码. 1.建立一个index.jsp用于表单提交 1 <%@ page language="java" contentType="text/html; charset=utf-8" 2 pageEncoding="utf-8"%> 3 <!DOCTYPE html PUBLIC "-//W3

springmvc和servlet下的文件上传和下载(存文件目录和存数据库Blob两种方式)

项目中涉及了文件的上传和下载,以前在struts2下做过,今天又用springmvc做了一遍,发现springmvc封装的特别好,基本不用几行代码就完成了,下面把代码贴出来: FileUpAndDown.jsp <%@ page language="java" contentType="text/html; charset=UTF-8"%> <html> <head> <title>using commons Uplo

使用jsp/servlet简单实现文件上传与下载

使用JSP/Servlet简单实现文件上传与下载 通过学习黑马jsp教学视频,我学会了使用jsp与servlet简单地实现web的文件的上传与下载,首先感谢黑马.好了,下面来简单了解如何通过使用jsp与servlet实现文件上传与下载. 在写代码之前,我们需要导入两个额外的jar包,一个是common-io-2.2.jar,另一个是commons-fileupload-1.3.1.jar,将这个两个jar 包导入WEB-INF/lib目录里. 首先,想要在web端即网页上实现文件上传,必须要提供

servlet3.0文件上传功能

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); //获取文件部件part Part part = request.getPart("file"); String h = part.getHeader(&

基于Servlet+smartUpload的文件上传

文件上传在web应用中是非常常见的,现在我就介绍下基于servlet的文件上传,基于Struts2的文件上传可以看: 页面端代码: <%@ page language="java" import="java.util.*" pageEncoding="GBK"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <ht

Servlet中的文件上传

上传表单中的注意事项: 表单 method 属性应该设置为 POST 方法,不能使用 GET 方法 表单 enctype 属性应该设置为multipart/form-data 下面的实例是借助于commons-fileupload和commons-io相关包来实现的 import java.io.*; import java.util.*; import javax.servlet.ServletConfig; import javax.servlet.ServletException; imp

Java Web开发之文件上传

文件上传有SmartUpload.Apache的Commons fileupload.我们今天介绍Commons fileupload的用法. 1.commons-io.jar 和commons-fileupload-1.3.1.jar 下载地址:http://pan.baidu.com/s/1kVtYMzH 2.web.xml 1 <!-- 上传文件 服务器端 --> 2 <servlet> 3 <servlet-name>UploadServlet</serv

普通的java Ftp客户端的文件上传

关于ftp上传文件其实并不难,但有时候面对现实的环境还是很蛋疼的,今天我就分享一下,普通的上传文件文件至FTP的方式,它满足大部分FTP,但也有特别的,下篇博客会提及到. 下面我用一个FtpUtil,来实现各种功能: 我们这里的主要功能是: 把本地文件夹下的文件上传到ftp的一个文件夹下 ,如果上传成功,就把上传成功的文件备份到另一个文件夹下,如果备份成功,就可以拿备份成功的文件删除了. 直接上代码了! package cn.tendency.utils; import java.io.File

Java 利用 SWFUpload多文件上传 session 为空失效,不能验证的问题

原文转自:http://www.tqcto.com/article/code/295299.html 我们都知道普通的文件上传是通过表单进行文件上传的,还不能达到异步上传的目的.通过使用某些技术手段,比如jquery form.js可以达到异步上传的目的,但最重要的问题在于,它不能够进行多个文件的上传.如果你要上传多个文件,必须一个一个地上传,同时还要在界面上处理当上传完一个文件之后,下一个文件上传框的问题.    现在我们有了一个更多的运行,即使用swfupload进行多文件异步上传.顾名思义