首页 > 其他分享 >第20章 SpringBoot上传文件

第20章 SpringBoot上传文件

时间:2024-11-06 09:20:17浏览次数:3  
标签:文件 20 SpringBoot springframework file import org 上传 String

在Spring Boot中实现文件上传仍然使用Spring MVC的MultipartFile类来处理。

我们创建一个 “SpringBootUploadDemo” 的工程

然后我们修改编码格式以及Maven仓库地址,我们省略这个过程了。

接下来,我们修改 “pom.xml” 文件,添加SpringBoot和Web依赖,如下所示

<?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.demo</groupId>
    <artifactId>SpringBootUploadDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.13</version>
        <relativePath/>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.7.18</version>
            </plugin>
        </plugins>
    </build>

</project>

接下来,我们创建 Appliaction 入口类文件

package com.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);
    }
}

接下来,我们创建 UploadController 控制器

package com.demo.controller;

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

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

@Controller
public class UploadController {

    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file, Map map) {

        String message = "";
        try {
            String uploadDir = "E:/idea-workspace/SpringBootUploadDemo/";
            File uploadedFile = new File(uploadDir + file.getOriginalFilename());
            file.transferTo(uploadedFile);
            message = "上传成功";
        } catch (IOException e) {
            e.printStackTrace();
            message = "上传失败:" + e.getMessage();
        }

        map.put("message", message);
        return "upload";
    }
    
}

我们将上传的文件保存到了 “E:/idea-workspace/SpringBootUploadDemo/” 工程目录下。

接下来,我们创建 “resources\static\index.html” 入口文件

<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>index</title>
</head>
<body>

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <button type="submit">上传</button>
</form>

</body>
</html>

文件上传通常使用 multipart/form-data 类型的 POST 请求。

接着,我们继续需要创建 “resources\templates\upload.html” 文件

<!doctype html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>upload</title>
</head>
<body>

<p th:text="${message}"></p>

</body>
</html>

接下来,我们运行测试一下啊

我们点击“选择文件”控件选择一张 “head.jpg” 图片

我们点击 “上传” 按钮

我们去 “E:/idea-workspace/SpringBootUploadDemo/” 工程目录下查看一下

如何在网页中显式这张图片呢?我们需要配置本地资源映射路径即可。

package com.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    private static final String UPLOAD_REQ = "/upload/**";
    private static final String UPLOAD_DIR = "E:/idea-workspace/SpringBootUploadDemo/";

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler(UPLOAD_REQ).addResourceLocations("file:///" + UPLOAD_DIR + "/");
    }

}

其中 “UPLOAD_REQ” 是我们的访问请求路径,而 “UPLOAD_DIR” 是映射的真实物理路径。我们配置一个拦截器, 如果访问路径是 addResourceHandler 中的 UPLOAD_REQ 这个路径,那么就 映射到访问本地的addResourceLocations 的 UPLOAD_DIR 参数的这个路径上。

我们只需要访问:http://localhost:8080/upload/head.jpg 就能看到刚刚上传的照片了。

我们重启测试一下

当然,我们还可以使用html中的img标签来显示这个图片。

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <button type="submit">上传</button>
</form>

<br />
<img src="http://localhost:8080/upload/head.jpg" />

接下来,我们简单介绍MultipartFile 的常用方法

getName():					获取文件在服务器上的文件名
getOriginalFilename():		获取文件在客户端上的原始文件名
getContentType():			获取文件的内容类型
isEmpty():					判断文件是否为空
getSize():					获取文件大小(字节)
getBytes():				读取文件内容为字节数组
getInputStream():			获取文件内容的输入流
getResource():				将文件转换为资源对象
transferTo(File dest):		将文件内容传输到指定的目标文件
transferTo(Path dest):		将文件内容传输到指定的目标路径

一般的文件上传,我们都会限制文件类型和大小,并且对文件进行重命名到指定目录下。很明显,我们可以通过 getContentType() 获取上传文件的类型,通过 getSize() 获取文件的大小,然后对其做限制。这里我们稍微介绍一下文件类型,也就是MIME 类型。MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的标准,用来表示文档、文件或字节流的性质和格式。常用的 MIME 类型如下所示

XML文件格式:text/xml
CSS样式表(css):text/css
普通文本格式(txt):text/plain
Javascript 脚本文件(js):text/javascript
HTML文件格式(htm, html, shtml):text/html

GIF图像格式(gif):image/gif
PNG图像格式(png):image/png
BMP图像格式(bmp):image/bmp
JPG2图像格式(jpg2):image/jp2
TIF(TIFF)图像格式(tif, tiff):image/tiff
JPG(JPEG)图像格式(jpg, jpeg):image/jpeg

PDF格式(pdf):application/pdf

ZIP压缩文件格式(zip):application/zip
RAR压缩文件格式(rar):application/rar

微软Office Word格式(doc):application/msword
微软Office Word格式(docx):application/vnd.openxmlformats-officedocument.wordprocessingml.document
微软Office Excel格式(xls):application/vnd.ms-excel
微软Office Excel格式(xlsx):application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
微软Office PowerPoint格式(ppt):application/vnd.ms-powerpoint
微软Office PowerPoint格式(pptx):application/vnd.openxmlformats-officedocument.presentationml.presentation

我们将各种限制和文件上传路径添加到配置文件 “application.properties” 中

upload-config.req = upload
upload-config.type = image/jpeg,image/png
upload-config.dir = E:/idea-workspace/SpringBootUploadDemo/

注意,我们的文件类型限制为jpg和png图片,它是一个List类型的配置项,使用逗号分隔多个MIME 类型。 接下来,我们使用一个配置类来读取 “application.properties” 中的配置项

package com.demo.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

@Data
@Component
@ConfigurationProperties(prefix = "upload-config")
public class UploadConfig {

    private String req;
    private String dir;
    private List<String> type;
}

Spring Boot工程嵌入的tomcat限制了请求的文件大小,每个文件的配置最大为1Mb,单次请求的文件的总数不能大于10Mb。我们需要修改配置文件(application.properties)中加入两个配置

spring.servlet.multipart.max-file-size = 5MB
spring.servlet.multipart.max-request-size = 5MB
server.tomcat.max-swallow-size = 100MB

注意,上面最重要的是要配置内嵌的 tomcat 的最大吞吐量即 max-swallow-size,可以设置 -1 不限制,也可以设置一下比较大的数字 100M。如果超过文件大小限制的话,就会抛出 “MaxUploadSizeExceededException” 异常,我们可以创建全局异常处理器来处理这个异常,代码如下

package com.demo.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ModelAndView handler(MaxUploadSizeExceededException  e) {

        e.printStackTrace();

        ModelAndView mv = new ModelAndView();
        mv.setViewName("exception");
        mv.addObject("message", "文件太大了");
        return mv;
    }

}

不要忘记补上 “resources\templates\exception.html” 文件

<!doctype html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>exception</title>
</head>
<body>

<div th:text="${message}"></div>

</body>
</html>

接下来,我们修改 “UploadController” 控制器

package com.demo.controller;

import com.demo.config.UploadConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

@Controller
public class UploadController {

    @Autowired
    private UploadConfig uploadConfig;

    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file, Map map) {

        String img = "";
        String message = "";
        try {
            // 检查文件类型
            List<String> fileTypeList = uploadConfig.getType();
            String fileType = file.getContentType().toLowerCase(Locale.ROOT);
            if(!fileTypeList.contains(fileType)){
                map.put("img", img);
                map.put("message", "文件类型不对:" + fileType);
                return "upload";
            }

            // 重命名
            String[] originalFileNameArray = file.getOriginalFilename().split("\\.");
            String newFileName = UUID.randomUUID().toString() + "." + originalFileNameArray[1];

            // 保存文件
            File uploadedFile = new File(uploadConfig.getDir() + newFileName);
            file.transferTo(uploadedFile);

            // 返回图片地址
            img = "/" + uploadConfig.getReq() + "/" + newFileName;
            message = "上传成功";

        } catch (IOException e) {
            e.printStackTrace();
            message = "上传失败:" + e.getMessage();
        }

        map.put("img", img);
        map.put("message", message);
        return "upload";
    }

}

我们判断了文件类型,顺便重新命名了上传文件,同时返回了上传文件图片地址。

不要忘记同步一下 “WebMvcConfig” 里面的代码

package com.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    //private static final String UPLOAD_REQ = "/upload/**";
    //private static final String UPLOAD_DIR = "E:/idea-workspace/SpringBootUploadDemo/";

    @Autowired
    private UploadConfig config;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        String pathPatterns = "/"+config.getReq()+"/**";
        registry.addResourceHandler(pathPatterns).addResourceLocations("file:///" + config.getDir() + "/");
    }

}

接下来,修改 “resources\templates\upload.html” 文件内容,增加图片的显示

<p th:text="${message}"></p>

<div th:if="${img}">
    <img th:src="${img}" />
</div>

接下来,我们重新运行测试一下啊

还是上传之前的 “head.jpg” 图片

上传成功,图片正常显示了,我们去项目根目录下查看

我们使用一个其他类型的大文件来测试一下

优先检查文件大小,上传的文件超过了 5M

继续测试

上传其他文件类型,大小没有超过5M,就可以检查文件类型了

接下来,我们使用控制器返回图片类型,一般使用输出流字节格式。

package com.demo.controller;

import com.demo.config.UploadConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

@Controller
public class UploadController {

    @Autowired
    private UploadConfig uploadConfig;

    @PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file, Map map) {

        String img = "";
        String message = "";
        try {
            // 检查文件类型
            List<String> fileTypeList = uploadConfig.getType();
            System.out.println("文件类型:" + fileTypeList.get(0).toLowerCase(Locale.ROOT));
            String fileType = file.getContentType().toLowerCase(Locale.ROOT);
            if(!fileTypeList.contains(fileType)){
                map.put("img", img);
                map.put("message", "文件类型不对:" + fileType);
                return "upload";
            }

            // 重命名
            String[] originalFileNameArray = file.getOriginalFilename().split("\\.");
            String newFileName = UUID.randomUUID().toString() + "." + originalFileNameArray[1];

            // 保存文件
            File uploadedFile = new File(uploadConfig.getDir() + newFileName);
            file.transferTo(uploadedFile);

            // 返回图片地址
            img = "/" + uploadConfig.getReq() + "/" + newFileName;
            message = "上传成功";

        } catch (IOException e) {
            e.printStackTrace();
            message = "上传失败:" + e.getMessage();
        }

        map.put("img", img);
        map.put("message", message);
        return "upload";
    }

    @GetMapping("/image")
    public ResponseEntity<byte[]> image() throws IOException {

        // 读取图片文件
        File file = new File(uploadConfig.getDir()+ "head.jpg");
        byte[] imageBytes = Files.readAllBytes(file.toPath());

        // 构建 HTTP 响应头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.IMAGE_JPEG);
        headers.setContentLength(imageBytes.length);

        // 返回包含图片字节数组的 ResponseEntity
        return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
    }

}

我们直接在 “resources\static\index.html” 入口文件中获取图片试试

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <button type="submit">上传</button>
</form>

<br />
<img src="http://localhost:8080/upload/head.jpg" />
<br />
<img src="/image" />

我们测试一下

接下来,我们演示图片文件下载

    @GetMapping("/download")
    public ResponseEntity<byte[]> download() throws IOException {

        // 读取图片文件
        String fileName = "head.jpg";
        File file = new File(uploadConfig.getDir() + fileName);
        byte[] imageBytes = Files.readAllBytes(file.toPath());

        // 构建 HTTP 响应头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentDispositionFormData("attachment", fileName);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

        // 返回客户端
        return new ResponseEntity<>(imageBytes, headers, HttpStatus.OK);
    }

我们在 “resources\static\index.html” 入口文件中添加下载链接

<br />
<img src="http://localhost:8080/upload/head.jpg" />
<br />
<img src="/image" />
<br />
<a href="/download" target="_blank">download</a>

接下来,我们重新运行测试一下

以下是返回Base64编码的图片字符串

    @GetMapping("/base64")
    public ResponseEntity<String> base64() throws IOException {

        // 读取图片文件
        File file = new File(uploadConfig.getDir()+ "head.jpg");
        byte[] imageBytes = Files.readAllBytes(file.toPath());

        // 将图片字节数组进行 Base64 编码
        String base64EncodedImage = Base64Utils.encodeToString(imageBytes);

        // 返回 Base64 编码后的图片字符串
        String body = "data:image/jpeg;base64," + base64EncodedImage;
        return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(body);
    }

前端使用ajax显示图片,使用src直接请求是不行的。

<script type="text/javascript">
function getImageWithBase64() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://localhost:8080/base64', true);
    xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
        var img = document.createElement("img");
        img.src = `${xhr.responseText}`;
        document.body.appendChild(img);
    }
  };
  xhr.send();
}
getImageWithBase64();
</script>

页面效果如下

本工程完整代码下载: https://download.csdn.net/download/richieandndsc/89953259

标签:文件,20,SpringBoot,springframework,file,import,org,上传,String
From: https://blog.csdn.net/richieandndsc/article/details/143556877

相关文章

  • GB/T 28046.3-2011 道路车辆 电气及电子设备的环境条件和试验 第3部分:机械负荷(10)
    写在前面本系列文章主要讲解道路车辆电气及电子设备的环境条件和试验GB/T28046标准的相关知识,希望能帮助更多的同学认识和了解GB/T28046标准。若有相关问题,欢迎评论沟通,共同进步。(*^▽^*)第3部分:机械负荷附录A振动试验曲线建立指南(资料性附录)A.5疲劳计算A.5.6通过......
  • 第21章 SpringBoot日志
    我们首先介绍一下开源日志框架。首先是commons-logging,是apache最早提供的日志框架。它的主要作用提供一个统一的日志接口,以便可以在不同的项目中使用不同的日志框架。common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志实现库(例如,jdk自带的logging库)。......
  • GB/T 28046.3-2011 道路车辆 电气及电子设备的环境条件和试验 第3部分:机械负荷(5)
    写在前面本系列文章主要讲解道路车辆电气及电子设备的环境条件和试验GB/T28046标准的相关知识,希望能帮助更多的同学认识和了解GB/T28046标准。若有相关问题,欢迎评论沟通,共同进步。(*^▽^*)第3部分:机械负荷4.1振动4.1.2试验4.1.2.8试验VIII——商用车分体式驾驶室4......
  • 网站上传修改数据库,通过FTP和后台管理修改数据库的步骤
    一、通过FTP上传数据库文件备份现有数据库在进行任何操作之前,首先备份现有的数据库。可以通过phpMyAdmin或其他数据库管理工具导出数据库文件。准备新的数据库文件准备好新的数据库文件(通常为SQL文件),确保文件内容正确无误。连接到FTP服务器使用FTP客户端连接到你......
  • springboot关爱老人App-计算机毕业设计源码32708
    目 录摘要1绪论1.1开发背景和意义1.2开发技术1.2.1Android开发工具1.2.2Springboot框架1.2.3MySQL数据库1.3论文结构与章节安排2系统分析2.1可行性分析2.2系统流程分析2.2.1用户注册流程2.2.2用户登录流程2.2.3数据删除流程2.3系......
  • springboot高校医务室管理系统-计算机设计毕业源码58407
    目 录摘 要1绪论1.1研究背景与意义1.2国内外研究现状1.3论文结构与章节安排1.4相关技术、工具简介2 高校医务室管理系统项目概述2.1可行性分析2.1.1技术可行性2.1.2 经济可行性2.1.3操作可行性2.2 系统功能分析2.2.1功能性分析2.2.2......
  • springboot整合redis详细教程
     前言什么是redis? Redis是一个开源的高性能键值存储系统,通常用作数据库、缓存或消息代理。以下是对Redis的详细介绍:1.基本特性速度快:Redis的读写速度非常快,可以达到每秒数万次的读写操作。多种数据结构:支持字符串、列表、集合、有序集合、散列、位图、超日志和地理......
  • 【2024潇湘夜雨】WIN11_Pro-Workstation_24H2.26120.2213软件选装纯净特别版11.5
    【系统简介】=============================================================1.本次更新母盘来自WIN11_Pro-Workstation_24H2.26120.2213.进桌面后稍等片刻,等待后续部分优化完成。2.全程离线精简、无人值守调用优化处理制作。部分优化适配系统可能要重启几次,即使显示适配失败也不......
  • IDEA 2024 安装激活教程(附激活补丁,亲测有效)
    第一步前往idea的官网,下载新版的idea下载完成后,进行安装,next,安装完成首次打开,会要求输入激活码才能使用第二步点击获取补丁文件保存下载之后进入文件夹***/JetBrains2023最新全家桶激活***找到文件/方式3:永久激活补丁+脚本(适合最新版本,可显示到2025年)点击进入/scr......