← 返回首页
SpringMVC教程(十四)
发表时间:2020-06-10 18:22:14
文件上传

通常使用ajax异步方式实现文件上传功能。

项目目录结构图如下:

实现步骤如下:

1.编写upload.html实现前端上传页面

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"
            integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    <style>
        #uploadImg{
            width: 400px;
            height: 300px;
        }
    </style>
</head>
<body>
<h1>文件上传</h1>
<hr>
<div>
    <form id="uploadForm" action="#" enctype="multipart/form-data">
        <table>
            <tr>
                <td class="title">上传照片:</td>
                <td><input type="file" id="file" name="file" value="选择图片" onchange="uploadFile()"/></td>
            </tr>
            <!--以下是实现图片预览-->
            <tr>
                <td colspan="2">
                    <img id="uploadImg" src="#"/>
                </td>
            </tr>
        </table>
    </form>
</div>

<script>
    //上传成功后的图片路径
    var uploadPath = "http://localhost:8888/springmvctest/upload/";
    function uploadFile() {
        let formData = new FormData($('#uploadForm')[0]);
        $.ajax({
            type: 'post',
            url: "http://localhost:8888/springmvctest/file/upload", //调用后台上传接口
            data: formData,
            cache: false,
            processData: false,
            contentType: false,
            success: function (data) {
                console.log(data);
                $('#uploadImg').attr("src",uploadPath+data.data);
            }
        });
    }

</script>
</body>
</html>

2.在pom.xml中添加commons-io上传组件依赖 Spring MVC实现上传必须依赖apache的commons-io组件。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.simoniu</groupId>
    <artifactId>springmvcdemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>springmvcdemo Maven Webapp</name>

    <properties>
        <spring.version>5.2.5.RELEASE</spring.version>
        <servlet-version>3.0.1</servlet-version>
        <jackson-versoin>2.10.0</jackson-versoin>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet-version}</version>
            <scope>compile</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson-versoin}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson-versoin}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson-versoin}</version>
        </dependency>


        <!--springmvc添加了上传文件解析器,必须添加commons-io/commons-fileupload的依赖-->
        <!--https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.4</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <!-- 此处的 1.8 指的是 JDK 的版本,目前一般为 1.7 或 1.8 -->
                    <target>1.8</target>
                </configuration>
            </plugin>
            <!--servlet容器 jetty插件-->
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.18.v20190429</version>
                <configuration>
                    <webApp>
                        <!--项目的上下文配置-->
                        <contextPath>/springmvctest</contextPath>
                    </webApp>
                    <!--项目的端口号和服务器配置-->
                    <httpConnector>
                        <port>8888</port>
                        <host>localhost</host>
                    </httpConnector>
                    <scanIntervalSeconds>1</scanIntervalSeconds>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3.在applicationContext.xml中注册文件上传解析器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 注册HandlerMapper、HandlerAdapter两个映射类 -->
    <mvc:annotation-driven />
    <!-- 访问静态资源 -->
    <mvc:default-servlet-handler/>

    <!-- 使用扫描机制扫描控制器类,控制器类都在controller包及其子包下 -->
    <context:component-scan base-package="com" />
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 定义文件上传的解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"/>
        <!-- 指定所上传文件的总大小不能超过200KB。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->
        <property name="maxUploadSize" value="2000000"/>
        <!--resolveLazily属性启用是为了推迟文件解析,以便在UploadController 中捕获文件大小异常-->
        <property name="resolveLazily" value="true"/>
    </bean>
</beans>

4.定义Controller返回的结果视图类Json.

package com.json;
import java.util.HashMap;
import java.util.Map;

/*
* Controller 返回的json格式类
*
* */
public class Json {

    //默认成功响应
    public static Map<String, Object> success(Object data) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 200);
        map.put("msg", "ok");
        map.put("data", data);
        return map;
    }

    //自定义消息的成功响应
    public static Map<String, Object> success(Object data,String msg) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 200);
        map.put("msg", msg);
        map.put("data", data);
        return map;
    }

    public static Map<String, Object> success(Object data,String msg,String token) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 200);
        map.put("msg", msg);
        map.put("data", data);
        map.put("token",token);
        return map;
    }

    //自定义消息的失败响应
    public static Map<String, Object> fail(String msg) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 400);
        map.put("msg", msg); // Json.fail("验证码不正确"); Json.fail("用户名和密码");
        return map;
    }
    //默认失败响应
    public static Map<String, Object> fail() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("code", 400);
        map.put("msg", "error");
        return map;
    }
}

5.完成MyUtils工具类里面封装了文件上传方法

package com.util;

import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.UUID;

public class MyUtils {

    public static String uploadFile(MultipartFile file,String path) throws Exception{

        String fileName = file.getOriginalFilename(); //获得上传文件的文件名
        //使用UUID生成一个不重复的文件名字。
        String uploadFileName = createUUIDFileName(fileName);

        //先判断文件的父目录是否存在,如果不存在先创建目录
        File uploadFile = new File(path,uploadFileName);
        if(!uploadFile.getParentFile().exists()){
            uploadFile.getParentFile().mkdirs();
        }
        //在判断文件是否存在,如果存在先删除,再创建。
        if(uploadFile.exists()){
            uploadFile.delete();
        }
        uploadFile.createNewFile();

        file.transferTo(uploadFile);
        return uploadFile.getName();

    }

    public static String createUUIDFileName(String fileName){
        String uuid =  UUID.randomUUID().toString().replace("-","");
        return uuid+fileName;
    }
}

6.完成UploadController文件上传控制器类

package com.controller;

import com.json.Json;
import com.util.MyUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

@RestController
@RequestMapping("file")
public class UploadController {

    @PostMapping("/upload")
    public Map<String,Object> upload(HttpServletRequest request) {
        System.out.println("开始上传...");
        MultipartHttpServletRequest multipartRequest
                = (MultipartHttpServletRequest) request;

        MultipartFile mFile = multipartRequest.getFile("file");
        System.out.println(mFile.getOriginalFilename());
        String path = request.getSession().getServletContext().getRealPath("/upload");
        System.out.println("上传绝对路径是:" + path);
        try{
            String image = MyUtils.uploadFile(mFile,path); //image 表示上传成功之后的文件名
            System.out.println("文件上传成功!");
            System.out.println("文件名是:" + image);

            return Json.success(image,"uploadSuccess");
        }
        catch(Exception ex){
            ex.printStackTrace();
            return Json.fail("uploadFailure");
        }
    }
}

7.测试文件上传