SpringBoot实现文件上传


SpringBoot实现文件上传
1、创建一个Springboot工程

2、改pom.xml


4.0.0


    org.springframework.boot
    spring-boot-starter-parent
    2.5.6
     


com.qbb
file-upload
0.0.1-SNAPSHOT

file-upload
Demo project for Spring Boot

    1.8


    
        org.springframework.boot
        spring-boot-starter-freemarker
    
    
        org.springframework.boot
        spring-boot-starter-web
    

    
        org.springframework.boot
        spring-boot-devtools
        runtime
        true
    
    
        org.springframework.boot
        spring-boot-configuration-processor
        true
    
    
        org.projectlombok
        lombok
        true
    
    
        org.springframework.boot
        spring-boot-starter-test
        test
    



    
        
            org.springframework.boot
            spring-boot-maven-plugin
            
                
                    
                        org.projectlombok
                        lombok
                    
                
            
        
    

3、写application.yml/properties文件
server:
port: 9001 # 配置端口号
spring:
freemarker:
suffix: .html # 设置视图模板后缀
cache: false # 不开启缓存

servlet:
multipart:
max-file-size: 10MB # 设置文件大小
enabled: true

4、主启动类
package com.qbb.springboot;

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

/**

  • @author QiuQiu&LL
  • @version 1.0
  • @createTime 2021-12-15 20:50
  • @Description:
    */
    @SpringBootApplication
    public class FileUploadMain9001 {
    public static void main(String[] args) {
    SpringApplication.run(FileUploadMain9001.class, args);
    }
    }

5、编写一个HelloController测试
package com.qbb.springboot.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**

  • @author QiuQiu&LL

  • @version 1.0

  • @createTime 2021-12-15 20:52

  • @Description:
    */
    @Controller
    public class HelloController {

    @ResponseBody
    @RequestMapping("/hello")
    public String hello() {
    return "Hello FileUpload";
    }

6、业务代码,处理文件上传
在资源目录resources目录下创建一个templates目录

创建一个文件上传的简单页面upload.html

文件上传

Springboot整合文件上传

  1. HelloController添加一下内容
    @RequestMapping("/upload")
    public String upload(){
    return "upload";
    }

  2. 测试

  3. 修改页面代码

  1. 修改controller层代码
    /**

    • 文件上传具体实现
    • @param multipartFile
    • @param request
    • @return
      */
      @PostMapping("/upload/file")
      @ResponseBody
      public String upload(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request){
      if(multipartFile.isEmpty()){
      return "文件有误!!!";
      }
      long size = multipartFile.getSize();
      String originalFilename = multipartFile.getOriginalFilename();
      String contentType = multipartFile.getContentType();//imgae/png;image/jpg;image/gif
      // if(!contentType.equals("png|jpg|gif")){ //伪代码 ,不正确的代码
      // return "文件类型不正确";
      // }
      // 1: 获取用户指定的文件夹。问这个文件夹为什么要从页面上传递过来呢?
      // 原因是:做隔离,不同业务,不同文件放在不同的目录中
      String dir = request.getParameter("dir");
      return uploadService.uploadImg(multipartFile,dir);
      }
  2. 配置文件可以配置文件上传相关信息
    servlet:
    multipart:
    enabled: true

    是单个文件大小 默认1M 10KB

    max-file-size: 2MB

    是设置总上传的数据大小

    max-request-size: 10MB

    当文件达到多少时进行磁盘写入

    file-size-threshold: 20MB

    设置临时目录

    location: F://data//tempxxxxxxxxxxxx

  3. 创建uploadService处理文件上传
    package com.qbb.springboot.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**

  • @author QiuQiu&LL

  • @version 1.0

  • @createTime 2021-12-15 21:07

  • @Description:
    */
    @Service
    @SuppressWarnings({"all"})
    public class UploadService {
    @Value("${file.uploadFolder}")
    private String uploadFolder;
    @Value("${file.staticPath}")
    private String staticPath;

    /**

    • MultipartFile 这个对象是springMvc提供的文件上传的接受的类,
    • 它的底层自动会去和HttpServletRequest request中的request.getInputStream()融合
    • 从而达到文件上传的效果。也就是告诉你一个道理:
    • 文件上传底层原理是:request.getInputStream()
    • @param multipartFile
    • @param dir
    • @return
      */
      public String uploadImg(MultipartFile multipartFile, String dir) {
      try {
      String realfilename = multipartFile.getOriginalFilename(); // 上传的文件:aaa.jpg
      // 2:截图文件名的后缀
      String imgSuffix = realfilename.substring(realfilename.lastIndexOf("."));// 拿到:.jpg
      // 3:生成的唯一的文件名:能不能用中文名:不能因为统一用英文命名。
      String newFileName = UUID.randomUUID().toString() + imgSuffix;// 将aaa.jpg改写成:SD23423k324-23423ms.jpg
      // 4:日期目录
      // SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
      // String datePath = dateFormat.format(new Date());// 日期目录:2021/10/27
      // 也可以使用JDK1.8的新时间类LocalDate/LocalDateTime
      LocalDate now = LocalDate.now();
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
      String formatDatePath = formatter.format(now);
      // 5: 指定文件上传以后的目录
      String servrepath = uploadFolder;// 这不是tomcat服务目录,别人不认识
      File targetPath = new File(servrepath + dir, datePath);// 生成一个最终目录:F://tmp/avatar/2021/10/27
      if (!targetPath.exists()) targetPath.mkdirs(); // 如果目录不存在:F://tmp/avatar/2021/10/27 递归创建
      // 6: 指定文件上传以后的服务器的完整的文件名
      File targetFileName = new File(targetPath, newFileName);// 文件上传以后在服务器上最终文件名和目录是:F://tmp/avatar/2021/10/27/SD23423k324-23423ms.jpg
      // 7: 文件上传到指定的目录
      multipartFile.transferTo(targetFileName);//将用户选择的aaa.jpg上传到F??/tmp/avatar/2021/10/27/SD23423k324-23423ms.jpg
      // 可访问的路径要返回页面
      // http://localhpst:9001/bbs/2021/10/27/5f61dea2-4b77-4068-8d0b-fdf415eac6df.png
      String filename = dir + "/" + datePath + "/" + newFileName;
      return staticPath + "/" + filename;
      } catch (IOException e) {
      e.printStackTrace();
      return "fail";
      }
      }
      }

9.测试

思考:从上面开似乎我们已经完成了文件上传,但是复制该地址会发现,无法通过http请求该服务资源
解决办法:
配置静态资源服务映射
package com.qbb.springboot.config;

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

/**

  • @author QiuQiu&LL

  • @version 1.0

  • @createTime 2021-12-16 10:39

  • @Description:
    */
    @Configuration
    public class WebMvcConfiguration implements WebMvcConfigurer {

    /**

    • springmvc让程序开发者配置文件上传额外的静态资源服务
    • @param registry
      */
      @Override
      public void addResourceHandlers(ResourceHandlerRegistry registry) {
      registry.addResourceHandler("/uploadimg/**").addResourceLocations("file:F://temp//");
      }
      }

核心代码分析
registry.addResourceHandler("访问的路径").addResourceLocations("上传资源的路径");
registry.addResourceHandler("/uploadimg/**").addResourceLocations("file:F://tmp//");

配置完成后测试一下

哈哈,功夫不负有心人,效果出现了!!!但是还有问题,我们发现有很多“死代码”不够灵活。如:/uploadimg/** file:F://temp//,都是我们写死的,如何改进呢?
使用配置文件环境隔离解决,使用

创建application-dev.yml开发环境配置文件和application-prod.yml生产环境配置文件
application-dev.yml

本机配置

file:
staticPath: http://localhost:9001
staticPatternPath: /upimages/**
uploadFolder: F:/tmp/

application-prod.yml

服务器配置

file:
staticPath: https://www.QIUQIU.com
staticPatternPath: /upimages/**
uploadFolder: /www/upload/

再来测试发现,依然可以