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/

再來測試發現,依然可以


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM