SpringBoot实现文件上传

SpringBoot实现文件上传

1、创建一个Springboot工程

2、改pom.xml

<?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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.qbb</groupId>
    <artifactId>file-upload</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>file-upload</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

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、业务代码,处理文件上传

  • 1.在资源目录resources目录下创建一个templates目录

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
<h1>Springboot整合文件上传</h1>
</body>
</html>
    1. HelloController添加一下内容
@RequestMapping("/upload")
public String upload(){
    return "upload";
}

    1. 测试
    1. 修改页面代码
<!--注意:
    enctype="multipart/form-data"
    method必须是post请求
    input的type是file类型,需要给上name值,controller才能获取
-->
<form action="/upload/file" enctype="multipart/form-data" method="post">
    <input name="dir" value="bbs">
    <input name="file" type="file">
    <input type="submit" value="文件上传">
</form>
    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);
    }
    1. 配置文件可以配置文件上传相关信息
servlet:
  multipart:
    enabled: true
    # 是单个文件大小 默认1M 10KB
    max-file-size: 2MB
    # 是设置总上传的数据大小
    max-request-size: 10MB
    #当文件达到多少时进行磁盘写入
    file-size-threshold: 20MB
    # 设置临时目录
    location: F://data//tempxxxxxxxxxxxx
    1. 创建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/

再来测试发现,依然可以

posted @   我也有梦想呀  阅读(2910)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示