编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

进阶篇-SpringBoot2.x实现文件上传

wxchong 2024-07-15 09:54:11 开源技术 12 ℃ 0 评论

1.本篇概要

文件上传在日常开发过程中比较常见的功能之一,SpringBoot中并没有提供额外的文件上传技术,还是依赖于SpringMVC的文件上传技术。我们要实现文件上传不需要引入其他依赖,spring-boot-starter-web中依赖的Spring框架已经给我们提供了相关功能。

2.MultipartFile

2.1 MultipartFile简介

在SpringMVC中提供了MultipartFile这个封装类,它包含了文件的二进制流和文件相关属性(文件名、大小等),而在Spring Boot中也是使用此封装类进行文件上传。

MultipartFile是个接口,它的实现类有CommonsMultipartFileStandardMultipartFile,这里做一下简单说明:

  • CommonsMultipartFile: 是基于apache fileupload的解析;
  • StandardMultipartFile: 是基于j2ee自带的文件上传进行解析,也就是使用Servlet3.0提供的javax.servlet.http.Part上传方式。

正常使用MultipartFile时,无需关心底层是以哪种方式进行文件上传处理的,SpringMVC会给我们做相应的转换。
另外要注意的是,如果想要实现文件上传,必须将表单的method设置为post,并将enctype设置为multipart/form-data。只有这样,浏览器才会把所选择文件的二进制数据发送给服务器。SpringMVC在文件上传时,会将上传的文件映射为MultipartFile对象,并对MultipartFile对象进行文件的解析和保存。

2.2 MultipartFile内的API方法

public interface MultipartFile extends InputStreamSource {

    //文件的接收参数 @RequestParam MultipartFile file 中的 file
    String getName();

    //获取上传文件的原名称;
    @Nullable
    String getOriginalFilename();

    //获取文件MIME类型,如application/pdf、image/pdf等;
    @Nullable
    String getContentType();

    //是否上传的文件是否为空;
    boolean isEmpty();

    //获取文件的字节大小,单位为byte;
    long getSize();

    //获取文件数据
    byte[] getBytes() throws IOException;

    //获取文件流;
    @Override
    InputStream getInputStream() throws IOException;

    //获得一个MultipartFile对象
    default Resource getResource() {
        return new MultipartFileResource(this);
    }

    //将上传的文件保存到目标文件中
    void transferTo(File dest) throws IOException, IllegalStateException;

    //将接收到的文件传输到给定的目标文件
    default void transferTo(Path dest) throws IOException, IllegalStateException {
        FileCopyUtils.copy(getInputStream(), Files.newOutputStream(dest));
    }
}

3. 单文件上传

3.1 表单提交

添加相关依赖包
主要是web依赖和thymeleaf模板依赖。

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-json</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2-extension</artifactId>
            <version>2.0.4</version>
        </dependency>
        <!--thymeleaf模板引擎 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

编写文件上传页面toUpload.html

<!DOCTYPE HTML>
<html>
<head>
    <title>upload page</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
</head>
<body>
<form enctype="multipart/form-data" method="post" action="/upload">
    文件: <input type="file" name="fileUpload"/>
    <input type="submit" value="上传"/>
</form>
</body>
</html>

编写配置application.yml

server:
  port: 8080
spring:
  servlet:
    multipart:
      enabled: true #是否支持批量上传
      max-file-size: 10MB #上传文件最大为 10M
      max-request-size: 100MB #上传请求最大为 100M
  thymeleaf:
    cache: false

创建文件上传的UploadController类

@Controller
public class FileUploadController {

    @RequestMapping("/toUpload")
    public String toUpload(){
        return "toUpload";
    }

    @ResponseBody
    @PostMapping("/upload")
    public Object upload(MultipartFile fileUpload){
        Map<String,Object> resultMap = new HashMap<>(8);

        //获取文件名
        String fileName = fileUpload.getOriginalFilename();
        //获取文件后缀名
        String suffixName = Objects.requireNonNull(fileName).substring(fileName.lastIndexOf("."));
        //重新生成文件名
        fileName = UUID.randomUUID() + suffixName;
        //指定本地文件夹存储图片
        try {
            String filePath = "E:\\file\\";
            File dir = new File(filePath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            File uploadFile = new File(filePath + fileName);
            fileUpload.transferTo(uploadFile);
            resultMap.put("msg","upload success");
            resultMap.put("code","10000");
            return resultMap;

        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("msg","upload failed");
            resultMap.put("code","10001");
            return resultMap;
        }
    }
}

测试结果如下




3.2 ajax方式提交

其他同3.1,增加页面以及Controller对应方法

    @RequestMapping("/toUpload2")
    public String toUpload2(){
        return "toUpload2";
    }

编写文件上传页面toUpload2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
</head>
<body>
<div id="result"></div>
<input type="file" id="file">
<input type="button" value="upload" onclick="fileUpload();">
<script>
    function fileUpload() {
        let file = $("#file")[0].files[0];
        let formData = new FormData();
        formData.append("file",file);
        $.ajax({
            url:'/upload',
            type:'post',
            processData:false,
            contentType:false,
            data:formData,
            success:function (data) {
                $("#result").html(data.msg);
            }
        });
    }
</script>
</body>
</html>

测试结果如下




4. 多文件上传

多文件上传其实把Controller中的MultipartFile改成数组即可

@Controller
public class MultiFileUploadController {

    @RequestMapping("/toMultiUpload")
    public String toMultiUpload(){
        return "toMultiUpload";
    }


    @ResponseBody
    @PostMapping("/upload2")
    public Object upload(MultipartFile[] files){
        Map<String,Object> resultMap = new HashMap<>(8);

        String filePath = "E:\\file\\";
        File dir = new File(filePath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        for(MultipartFile file: files){
            //获取文件名
            String fileName = file.getOriginalFilename();
            //获取文件后缀名
            String suffixName = Objects.requireNonNull(fileName).substring(fileName.lastIndexOf("."));
            //重新生成文件名
            fileName = UUID.randomUUID() + suffixName;
            File uploadFile = new File(filePath + fileName);
            try {
                file.transferTo(uploadFile);
                resultMap.put("msg","upload success");
                resultMap.put("code","10000");
            } catch (IOException e) {
                e.printStackTrace();
                resultMap.put("msg","upload failed");
                resultMap.put("code","10001");
            }
        }
        return resultMap;
    }
}

前端页面表单中添加multiple属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>multi upload</title>
</head>
<body>
<form action="upload2" method="post" enctype="multipart/form-data">
    <input type="file" name="files" multiple>
    <input type="submit" value="Upload">
</form>
</body>
</html>

测试结果如下



本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表