JavaWeb四种文件上传方式(下篇)

上篇我们学完了Servlet2.5传统上传Servlet3.0原生无依赖上传 ;下篇则讲解SpringMVC两种主流文件上传写法。 Java Web 四种文件上传方式(上篇)-CSDN博客

环境:JDK8 + Tomcat8.5 + SpringMVC + Maven


三、SpringMVC文件上传方式一:形参直接接收 MultipartFile

1. 简介

SpringMVC 对原生文件上传做了封装,不用手动解析请求、遍历 FileItem和操作 Part

要点:

  1. 必须在 springmvc.xml 配置 文件上传解析器 multipartResolver
  2. 控制器方法直接用 MultipartFile 形参接收,参数名和表单 name 一致
  3. 自动封装上传文件、自动处理请求转码,只需要做:重命名 + 保存
  4. 依然要求表单加:enctype="multipart/form-data"

2. 必须的 Maven 依赖

XML 复制代码
<!-- SpringMVC核心依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>

<!-- servlet依赖 -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

<!-- 文件上传基础包 SpringMVC底层依赖这两个 -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

3. SpringMVC 配置文件 springmvc.xml 重点配置

必须配置 multipartResolver,id 不能改 固定写法:

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

    <!-- 包扫描 -->
    <context:component-scan base-package="com.qcby.controller"/>

    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- 必须配置:SpringMVC文件上传解析器  id固定为multipartResolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 编码格式 -->
        <property name="defaultEncoding" value="UTF-8"/>
        <!-- 单个文件最大大小 10M -->
        <property name="maxUploadSizePerFile" value="10485760"/>
    </bean>

    <!-- 开启注解驱动 -->
    <mvc:annotation-driven/>
</beans>

4. 上传表单 jsp

XML 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>SpringMVC文件上传方式一</title>
</head>
<body>
<form action="/uploadFile1" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="file"><br>
    <input type="submit" value="SpringMVC上传">
</form>
</body>
</html>

5. 控制器完整代码

java 复制代码
package com.qcby.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Controller
public class FileUploadController1 {

    @RequestMapping("/uploadFile1")
    public String uploadFile(MultipartFile file) throws IOException {
        // 1. 判断是否为空文件
        if (file.isEmpty()) {
            System.out.println("未选择文件或文件为空");
            return "error";
        }

        // 2. 获取原始文件名
        String originalFilename = file.getOriginalFilename();

        // 3. 截取文件后缀
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        // 4. UUID生成唯一文件名 防止重名覆盖
        String newFileName = UUID.randomUUID().toString().replace("-", "") + suffix;

        // 5. 定义保存路径 不存在自动创建文件夹
        File saveDir = new File("D:/AuploadMVC1");
        if (!saveDir.exists()) {
            saveDir.mkdirs();
        }

        // 6. 执行文件保存
        File destFile = new File(saveDir, newFileName);
        file.transferTo(destFile);

        System.out.println("SpringMVC方式一上传成功:" + destFile.getAbsolutePath());
        return "suc";
    }
}

方式一特点

  1. 最简,企业开发最常用
  2. 直接形参接收 MultipartFile,代码少
  3. 配置 multipartResolver 解析器
  4. 参数名和表单 file 的 name 必须一致

四、SpringMVC文件上传方式二:强转 MultipartHttpServletRequest

1. 简介

原理:把原生 HttpServletRequest 强转为 MultipartHttpServletRequest,再通过 getFileMap() 获取所有上传文件,再根据 name 取出对应文件。

适用场景:需要一次性接收多个文件、或者手动管理请求对象时使用,底层和方式一本质一样,只是接收写法不同。

2. 依赖 & springmvc.xml

和上面方式一一样,不用重复改配置。

3. 上传表单 jsp

XML 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>SpringMVC文件上传方式二</title>
</head>
<body>
<form action="/uploadFile2" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="file"><br>
    <input type="submit" value="上传提交">
</form>
</body>
</html>

4. 控制器完整代码

java 复制代码
package com.qcby.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;

@Controller
public class FileUploadController2 {

    @RequestMapping("/uploadFile2")
    public String uploadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("进入SpringMVC上传方式二");

        // 1. 把原生request强转为多部件上传请求
        MultipartHttpServletRequest mr = (MultipartHttpServletRequest) request;

        // 2. 获取所有上传文件Map集合
        Map<String, MultipartFile> fileMap = mr.getFileMap();

        // 3. 根据表单name获取文件
        MultipartFile pic = fileMap.get("file");

        // 4. 判断文件是否为空
        if (pic.isEmpty()) {
            System.out.println("未选择文件或文件为空");
            return "error";
        }

        // 5. 获取原始文件名
        String filename = pic.getOriginalFilename();

        // 6. UUID重构唯一文件名
        String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
        filename = uuid + "_" + filename;

        // 7. 构建保存目录 自动创建
        File file1 = new File("D:/AuploadMVC2");
        if (!file1.exists()) {
            file1.mkdirs();
        }

        // 8. 保存文件
        pic.transferTo(new File(file1, filename));

        System.out.println("SpringMVC方式二上传成功:" + filename);
        return "suc";
    }
}

方式二特点

  1. 手动强转 Request,更贴近底层
  2. 可以一次性获取多个文件,适合多文件上传
  3. 同样依赖 multipartResolver 配置
  4. 代码比方式一稍多,适合学习底层原理

五、四种文件上传

1. 四种方式归类

  1. Servlet2.5 传统上传:依赖 commons 包,代码繁琐,老项目遗留
  2. Servlet3.0 原生上传 :无需第三方依赖,@MultipartConfig + getPart()
  3. SpringMVC 方式一 :直接形参 MultipartFile,最简
  4. SpringMVC 方式二 :强转 MultipartHttpServletRequest,适合多文件、底层理解

2. 共同点

  1. 文件上传表单必须加enctype="multipart/form-data"
  2. 都要UUID / 时间戳重命名,防止同名文件覆盖
  3. 都要手动判断保存目录是否存在,不存在则创建
  4. SpringMVC 必须配置 multipartResolver 上传解析器
相关推荐
TE-茶叶蛋1 小时前
深入研究 yudao-framework 模块:Java 编程能力提升指南
java·开发语言
逻辑驱动的ken2 小时前
Java高频考点场景题24
java·开发语言·面试·职场和发展·求职招聘
兔小盈2 小时前
多线程-(五)线程安全之内存可见性
java·开发语言·多线程
CeshirenTester2 小时前
LangChain的工具调用 vs 原生Skill API:性能差在哪儿?
java·人工智能·langchain
yaoxin5211232 小时前
400. Java 文件操作基础 - 使用 Buffered Stream I/O 读取文本文件
java·开发语言·python
Fox爱分享2 小时前
字节二面:10亿数据毫秒级查手机尾号后4位,答不出“异构索引”直接挂?
java·后端·面试
6190083362 小时前
win idea 控制台中文乱码
java·ide·intellij-idea
折哥的程序人生 · 物流技术专研3 小时前
《Java面试85题图解版(二)》进阶深化上篇:并发编程 + JVM
java·开发语言·后端·面试
abcnull3 小时前
用ASM做精准测试(Java)
java·jar·asm·字节码·精准测试