Java文件上传的多种方式

文章目录
  1. 前言
  2. 实现文件上传功能的具体步骤
    1. 一、表单提交commons-fileupload文件上传的实现方式
    2. 二、ajax无刷新页面的文件上传方式

前言

本文讨论基于Java SpringMVC框架的文件上传,将会详细说明基于Apache commons-fileupload的文件上传,其中,会介绍通过ajaxfileupload无刷新的ajax文件上传。

实现文件上传功能的具体步骤

1. 导入Apache commons-fileupload文件上传所需要的jar包
为了实现基于Apache commons-fileupload的文件上传,我们需要首先导入所需要的apache jar包,如下maven依赖项:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>

4. 配置web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<!-- SpringMVC的前端控制器 -->
<servlet>
<servlet-name>ServletDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Spring MVC配置文件结束 -->
<servlet-mapping>
<servlet-name>ServletDispatcher</servlet-name>
<!-- 由SpringMVC拦截所有请求 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

3. 在springmvc-servlet.xml配置文件中设置文件上传的相应配置细节

1
2
3
4
5
6
<!--文件上传 upload file 配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<!--最大上传文件大小, -1为不限制-->
<property name="maxUploadSize" value="-1"/>
</bean>

4. UploadController的实现

  • commens-fileupload上传文件方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public String upload(MultipartFile file, HttpServletRequest request, Model model) throws IOException {
    if(file.isEmpty()) {
    System.out.println("文件不存在");
    return null;
    }
    // 获得原始文件名
    String fileName = file.getOriginalFilename();
    System.out.println("原始文件名:" + fileName);
    // 新文件名
    String name = UUID.randomUUID() + fileName;
    // 获得项目的路径
    ServletContext sc = request.getSession().getServletContext();
    // 上传位置
    String realPath = sc.getRealPath("/WEB-INF/upload");
    FileUtils.copyInputStreamToFile(file.getInputStream(), new File(realPath, name));
    System.out.println("文件上传成功");
    return null;
    }
  • 文件流上传方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public String upload(MultipartFile file, HttpServletRequest request, Model model) throws IOException {
    if(file.isEmpty()) {
    System.out.println("文件不存在");
    return null;
    }
    // 获得原始文件名
    String fileName = file.getOriginalFilename();
    System.out.println("原始文件名:" + fileName);
    // 新文件名
    String name = UUID.randomUUID() + fileName;
    // 获得项目的路径
    ServletContext sc = request.getSession().getServletContext();
    // 上传位置
    String realPath = sc.getRealPath("/WEB-INF/upload");
    File saveFile = new File(realPath, name);
    file.transferTo(saveFile);
    System.out.println("文件上传成功");
    return null;
    }
  • 一次上传多个文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    @RequestMapping(value="/add", method=RequestMethod.POST)
    public String addUser(User user, @RequestParam MultipartFile[] myfiles, HttpServletRequest request) throws IOException{
    //如果只是上传一个文件,则只需要MultipartFile类型接收文件即可,而且无需显式指定@RequestParam注解
    //如果想上传多个文件,那么这里就要用MultipartFile[]类型来接收文件,并且还要指定@RequestParam注解
    //并且上传多个文件时,前台表单中的所有<input type="file"/>的name都应该是myfiles,否则参数里的myfiles无法获取到所有上传的文件
    for(MultipartFile myfile : myfiles){
    if(myfile.isEmpty()){
    System.out.println("文件未上传");
    } else {
    System.out.println("文件长度: " + myfile.getSize());
    System.out.println("文件类型: " + myfile.getContentType());
    System.out.println("文件名称: " + myfile.getName());
    System.out.println("文件原名: " + myfile.getOriginalFilename());
    System.out.println("========================================");
    //如果用的是Tomcat服务器,则文件会上传到\\%TOMCAT_HOME%\\webapps\\YourWebProject\\WEB-INF\\upload\\文件夹中
    String realPath = request.getSession().getServletContext().getRealPath("/WEB-INF/upload");
    //这里不必处理IO流关闭的问题,因为FileUtils.copyInputStreamToFile()方法内部会自动把用到的IO流关掉,我是看它的源码才知道的
    FileUtils.copyInputStreamToFile(myfile.getInputStream(), new File(realPath, myfile.getOriginalFilename()));
    }
    }
    return null;
    }

至此,上述内容为普通表单提交上传文件方式和ajax文件上传文件的公共部分。

一、表单提交commons-fileupload文件上传的实现方式

  1. 前端页面的实现:
    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
    49
    50
    51
    52
    53
    54
    55
    <html>
    <div id="page-content-wrapper">
    <div id="page-title">
    <h3>
    上传文件
    </h3>
    </div>
    <div id="page-content">
    <form id="form" action="/upload" method="POST" enctype="multipart/form-data">
    <div class="col-md-12">
    <div class="form-row">
    <div class="form-label col-md-2">
    <label for="">
    文件
    <span class="required">*</span>
    </label>
    </div>
    <div class="form-input col-md-2">
    <input type="file" id="file" name="file" data-trigger="change" data-required="true"
    class="parsley-validated"
    value="">
    </div>
    </div>
    <div class="row pad5A">
    <div class="form-input col-md-1 col-md-offset-1">
    <a href="javascript:save();" class="btn large primary-bg radius-all-4" id="save">
    <span class="button-content">
    提交
    </span>
    </a>
    </div>
    <div class="form-input col-md-1">
    <a href="/finance/financedata" class="btn large primary-bg radius-all-4" id="back">
    <span class="button-content">
    返回
    </span>
    </a>
    </div>
    </div>
    </div>
    </form>
    </div>
    </div>
    <script type="text/javascript" src="/assets/js/jquery-1.12.4.min.js"></script>
    <script type="text/javascript" src="/assets/js/ajaxfileupload.js"></script>
    <script>
    // 提交
    function save() {
    $('#form').parsley('validate');
    $('#form').submit();
    }
    </script>
    </html>

当点击提交按钮时,页面将会触发form表单的submit,页面将进行刷新并提交file文件,并访问UploadController中的/upload接口;
此处,form表单必须注明表单提交的是文件类型,即如下代码中的enctype="multipart/form-data"设置,否则,页面将无法识别提交的内容,造成文件上传时失败;

1
<form id="form" action="/upload" method="POST" enctype="multipart/form-data">

二、ajax无刷新页面的文件上传方式

  1. 在实现ajax上传之前,我们的前端页面需要依赖ajaxfileupload.js文件进行依赖,ajaxfileupload的下载请自行搜索;需要说明的是,我们需要对ajaxfileupload.js文件进行修改,否则,在执行文件上传的过程中,将会出现如下2个错误:
  • a.jQuery.handleError is not a function;
    解决方法(handlerError只在jquery-1.4.2之前的版本中存在,jquery-1.6 和1.7中都没有这个函数了):
    在ajaxfileupload.js文件中添加如下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    handleError: function( s, xhr, status, e ) {
    // If a local callback was specified, fire it
    if ( s.error ) {
    s.error.call( s.context || s, xhr, status, e );
    }
    // Fire the global callback
    if ( s.global ) {
    (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
    }
    }
  • b.文件上传成功后,js将不会回调success:{}中的方法;
    解决方法:
    在ajaxfileupload.js文件中添加如下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    uploadHttpData: function( r, type ) {
    var data = !type;
    data = type == "xml" || data ? r.responseXML : r.responseText;
    // If the type is "script", eval it in global context
    if ( type == "script" )
    jQuery.globalEval( data );
    // Get the JavaScript object, if JSON is used.
    if ( type == "json" )
    data = jQuery.parseJSON(jQuery(data).text());
    // evaluate scripts within html
    if ( type == "html" )
    jQuery("<div>").html(data).evalScripts();
    //alert($('param', data).each(function(){alert($(this).attr('value'));}));
    return data;
    }
  1. 前端页面的实现
    在该实现中,javascript的元素fileElementId: "file" 表示需上传的文件的控件id,即html代码中的<input type="file" name="file" id="file"/>,该javascript代码即获取id为file的文件进行上传操作;
    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
    <html>
    <body>
    <div>
    <label>
    文件:
    </label>
    <input type="file" name="file" id="file"/>
    </div>
    </body>
    <script type="text/javascript" src="/assets/js/jquery-1.12.4.min.js"></script>
    <script type="text/javascript" src="/assets/js/upload/ajaxfileupload.js"></script>
    <script>
    function ajaxFileUpload() {
    $.ajaxFileUpload({
    url: "/upload",
    secureuri: false,
    data: {
    tag: version
    },
    fileElementId: "file",
    dataType: "json",
    success: function (data) {
    if (data && data.status == 0) {
    //上传成功
    } else {
    // 上传失败
    }
    },
    error {
    // 处理异常
    }
    });
    }
    </script>
    </html>