SpringBoot 文件上传

可参考:>>>javaWeb 文件上传 【原生servlet】<<<
可参考:>>>SpringMVC的文件上传<<<

一、前言

1、问题

  • 以前只使用Spring MVC时,使用如下方式获得路径,在项目的out文件夹下

    String path = request.getServletContext().getRealPath("/upload")
    
  • 但是在SpringBoot中此方法获得的路径类似为: C:\Users\25293\AppData\Local\Temp\ tomcat.8080.3028400654015009944

  • 并且,每次重新启动项目,都会生成一个新的文件夹(本地运行)

2、原因

  • 当使用tomcat发布项目的时候,上传文件存放非常简单,因为可以随意操作项目路径下的资源。

    但当使用SpringBoot的jar包发布项目时,不再能像以前一样操作文件了,而是只能使用InputStream读取里面的文件

3、解决办法

  • 此时,我们有三种方式解决问题:

    1. 为它构建一个文件服务器
    2. 指定一个具体的绝对路径;
    3. 存放在与jar包同级的static文件夹下的upload文件夹(以下介绍的就是这种)。
  • 其中,我们使用SpringBoot的工具类ResourceUtils获取路径

    String path = ResourceUtils.getURL("classpath:").getPath() + "static/upload/";
    
  • 此时路径位置为:

    • 本地运行时:${项目路径}/target/classes/static/upload
    • 发布到服务器运行时:${jar包所在路径}/static/upload

二、上传功能具体实现

1、导入依赖的jar包,配置application.yaml

  • 正如Spring MVC,SpringBoot也使用Apache Commons FileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver。
  • 因此,SpringBoot的文件上传还需要依赖Apache Commons FileUpload的组件。
<!--文件上传-->
<dependency>
   <groupId>commons-fileupload</groupId>
   <artifactId>commons-fileupload</artifactId>
   <version>1.4</version>
</dependency>
  • 配置application.yaml
# 文件上传
spring:
  servlet:
    multipart:
      # 开启功能
      enabled: true
      # 单个文件最大10MB(默认1MB)
      max-file-size: 10MB
      # 请求最大20MB(默认10MB)
      max-request-size: 20MB
  # 静态路径
  resources:
    static-locations: classpath:static/,file:static/
  • 关于配置静态路径,如果只是在本地跑项目,可能你感受不出来配置不配置的区别,但如果发布到服务器上,没有配置的话上传成功后无法访问

2、后端 FileController.java 和工具类 UploadFile.java

  • FileController.java
package com.shiyq.controller;

import com.shiyq.util.UploadFile;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.ui.Model;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class FileController {
    /**
     * 文件上传
     * 采用file.Transto 来保存上传的文件
     * @RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile对象
     * 批量上传CommonsMultipartFile则为数组即可
     * 
     * @param username 页面传来的普通输入框的值
     * @param file 文件对象
     * @return 跳转 查看上传的图片
     */
    @RequestMapping("/upload")
    public String  fileUpload2(@RequestParam("username") String username,
                               @RequestParam("file") MultipartFile file,
                               Model model) {
        if (file != null) {
            String filePath = UploadFile.uploadFile(file);
            model.addAttribute("filePath", filePath);
        }
        return "show";
    }

}
  • 工具类 UploadFile.java
package com.shiyq.util;

import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

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

/**
 * @author shiyq
 * @create 2021-02-26 21:05
 */
public class UploadFile {

    // 绝对路径
    private static String absolutePath = "";
    // 上传文件存放位置
    private static String uploadDir = "static/upload/";

    /**
     * 单文件上传
     * @param file  需要上传的文件
     * @return  文件名
     */
    public static String uploadFile(MultipartFile file) {
        // 如果路径不存在则创建
        createDirIfNotExists();
        // 获取文件后缀名,如果不需要".",可以在最后+1,此处可增加对文件类型的筛选
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        // 更改文件名,防重名
        String headImg = UUID.randomUUID().toString() + suffix;
        //通过CommonsMultipartFile的方法直接写文件
        try{
            file.transferTo(new File(absolutePath + headImg));
        } catch (IOException e){
            e.printStackTrace();
        }
        return headImg;
    }

    /**
     * 创建与springboot打包的jar同级的static的upload文件夹
     */
    public static void createDirIfNotExists() {
        if (!absolutePath.isEmpty()) return;

        //获取根目录
        File path = null;
        try {
            path = new File(ResourceUtils.getURL("classpath:").getPath());
        } catch (FileNotFoundException e) {
            throw new RuntimeException("获取根目录失败,无法创建上传目录!");
        }
        if (!path.exists())
            path = new File("");

        absolutePath = path + uploadDir;

        File uploadPath = new File(absolutePath);
        if(!uploadPath.exists()) {
            uploadPath.mkdirs();
        }
    }

}

2、前端 upload.html 和 show.html

  • 上传表单 upload.html
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
    <body>
        <!-- 
			th标签:SpringBoot推荐使用的thymeleaf
			enctype="multipart/form-data" 将表单转换为二进制进行传输,文件上传必须加上
			POST:上传文件大小没有限制
		-->
        <form th:action="@{/upload}" 
              enctype="multipart/form-data"  
              method="post">
            普通输入框:<input type="text" name="username"><br/>
            <P><input type="file" name="file"></P>
            <P><input type="submit" value="提交"></P>
        </form>
    </body>
</html>
  • 查看上传的图片 show.html
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
    <body>
        <img th:src="@{'/upload/'+${filePath}}"
    </body>
</html>

三、异常

  • ConFileController.java中的

    @RequestParam("file") MultipartFile file 
    // 也可以写为
    @RequestParam("file") CommonsMultipartFile file,
    
  • 但此时会报异常

    Resolved [org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: Failed to convert value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'org.springframework.web.multipart.commons.CommonsMultipartFile'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'org.springframework.web.multipart.commons.CommonsMultipartFile': no matching editors or conversion strategy found]
    
    
  • 有两种解决办法:

    1. CommonsMultipartFile 替换为: MultipartFile

    2. 在配置SpringBoot类中加入如下Bean

      @Bean
      public CommonsMultipartResolver getCommonsMultipartResolver() {
          CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
          multipartResolver.setMaxUploadSize(20971520);
          multipartResolver.setMaxInMemorySize(1048576);
          return multipartResolver;
      }
      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot中实现文件非常简单。首先,你需要在项目的依赖中添加spring-boot-starter-web。然后,你可以通过配置文件来对文件进行一些基本的配置。例如,你可以设置是否开启文件支持、文件写入磁盘的阈值、上文件的临时保存位置、上的单个文件的最大大小以及多文件文件的总大小等。\[1\] 对于单文件,你可以创建一个HTML表单,使用enctype="multipart/form-data"来指定表单的编码类型,并使用<input type="file">来选择文件。然后,你可以在后端编写一个处理文件的接口,通过@RequestParam注解来获取上文件。\[2\] 对于多文件,你可以创建一个HTML表单,使用相同的方式来选择多个文件。然后,你可以在后端编写一个处理多文件的接口,通过@RequestParam注解来获取上文件列表。\[2\] 在Spring Boot中,如果你没有提供MultipartResolver,那么默认采用的MultipartResolver就是StandardServletMultipartResolver。因此,你甚至可以实现零配置的文件。\[3\] 总结起来,Spring Boot提供了简单而强大的功能来实现文件,你只需要添加依赖、进行一些基本的配置,然后在后端编写相应的接口即可实现文件功能。 #### 引用[.reference_title] - *1* *2* *3* [SpringBoot文件](https://blog.csdn.net/qq_43581790/article/details/123811775)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值