45. 지정된 디스크 경로에 springboot 파일을 업로드하고 업로드 성공 후 파일 에코를 업로드합니다.

요구 사항:
지정된 폴더에 파일을 업로드하는 파일 업로드 함수를 작성하세요.
그런 다음 업로드가 성공한 후 파일이 에코됩니다.

★ Spring Boot는 파일 업로드에 대한 자동 구성 지원을 제공합니다.

Spring Boot的文件上传自动配置主要由 MultipartAutoConfiguration 和 MultipartProperties 两个类组成。

MultipartProperties负责加载 spring.servlet.multipart.* 开头的配置属性。

MultipartAutoConfiguration 则根据 MultipartProperties 读取的配置属性来初始化
StandardServletMultipartResolver 解析器对象。

MultipartAutoConfiguration: 파일 업로드를 처리하는 클래스입니다.
MultipartProperties : 구성 파일에서 spring.servlet.multipart.*로 시작하는 구성 속성을 읽는 데 사용되는 속성 처리 클래스입니다.

★ MultipartProperties 클래스에서 지원되는 파일 업로드 관련 구성 속성

# 设置每个文件上传域的最大大小
spring.servlet.multipart.max-file-size=10MB
# 设置整个请求支持的最大大小
spring.servlet.multipart.max-request-size=50MB
# 设置文件上传的中转目录
spring.servlet.multipart.location=d:/temp

★ 파일 업로드 단계

(1) 프런트 엔드 페이지의 파일 요청은 "multipart/form-data" 인코딩 방법으로 제출됩니다.

(2) MultipartFile 유형의 속성을 정의하여 파일 업로드 도메인을 캡슐화합니다.

(3) 업로드된 파일은 MultipartFile 속성을 통해 접근할 수 있으며, 해당 파일은 어떤 디렉터리(또는 데이터베이스)에도 쓸 수 있습니다.

▲ 파일 업로드 에코를 확인하시길 바랍니다

 能看到上传后文件的图片,

 (1)需要将服务器保存文件的所使用的文件名传回给视图页面。

 (2)还需要将保存文件的路径设置为Spring Boot的静态资源路径。
      添加额外的静态资源路径时,额外添加的磁盘最后必须要有一个斜杠结尾

파일 업로드: 코드 데모:

파일 업로드 페이지를 더 보기 좋게 만들려면 이러한 파일 업로드 컨트롤이 필요합니다. 이 파일 업로드 인터페이스 구성 요소를 추가하십시오.
여기에 이미지 설명을 삽입하세요.

질문: 여기에서 파일을 선택했는데 파일 이름이 표시되지 않는 이유는 무엇입니까
여기에 이미지 설명을 삽입하세요.
? 해결책:
js 파일이 위에서 아래로 실행되기 때문입니다.
여기에 이미지 설명을 삽입하세요.
효과:
파일을 선택하면 파일 이름이 성공적으로 표시됩니다.성공한 이유는 bsCustomFileInput.init()를 통해 전체 페이지를 로드한 후 custom-file-input 구성 요소를 초기화하기 때문입니다. 파일 이름이 성공적으로 표시되도록 하십시오.
여기에 이미지 설명을 삽입하세요.

메소드 매개변수 소개:
여기에 이미지 설명을 삽입하세요.
요청 매개변수가 너무 많으면 하나씩 작성할 수 없으므로 요청 매개변수를 객체에 캡슐화하면 됩니다.
여기에 이미지 설명을 삽입하세요.

완전한 코드

파일을 추가하는 페이지:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    <!--  引入css样式,用 link 元素  ,  stylesheet 样式单 , .gz表示是打包的,但是springboot会自动解包 -->
    <!--  引入 Bootstrap 的 Web Jar 中的 CSS 样式  -->
    <link rel="stylesheet" th:href="@{'/webjars/bootstrap/css/bootstrap.min.css'}">
    <!--  jquery 放在 bootstrap 前面,因为 bootstrap 需要依赖到 jquery  -->
    <!--  引入 jQuery 的 Web Jar 中的 js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/jquery/jquery.min.js'}"></script>
    <!--  引入 Bootstrap 的 Web Jar 中的 js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/bootstrap/js/bootstrap.bundle.min.js'}"></script>
    <!--  引入 popper 的 Web Jar 中的 Js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/popper.js/umd/popper.min.js'}"></script>
    <!--  引入文件上传的界面组件的js  -->
    <script type="text/javascript"
            th:src="@{'/webjars/bs-custom-file-input/dist/bs-custom-file-input.js'}"></script>
    <script>
        // <!-- 当整个页面加载完成的时候,就执行这个函数,保证这个函数是在页面加载完成后才执行初始化 -->
        // <!-- 初始化 custom file input 组件的 JS 脚本 -->
        $(function () {
    
    
            bsCustomFileInput.init();
        })
    </script>
</head>
<body>
<div class="container">
    <h4>添加图书</h4>
    <!-- 保证请求是以 multipart/form-data 格式提交请求
     不用这个格式,文件上传的数据都不会传到服务器 -->
    <form method="post" th:action="@{/addBookFile}" enctype="multipart/form-data">
        <div class="form-group row">
            <label for="name" class="col-sm-2 col-form-label">图书名:</label>
            <div class="col-sm-7">
                <input type="text" id="name" name="name"
                       class="form-control" placeholder="请输入图书名">
            </div>
            <div class="col-sm-3 text-danger">
                <span th:if="${book != null}" th:errors="${book.name}">错误提示</span>
            </div>
        </div>
        <div class="form-group row">
            <label for="cover" class="col-sm-2 col-form-label">图书封面:</label>
            <div class="col-sm-7">
                <!--  custom-file 用来保证页面比较好看  -->
                <div class="custom-file">
                    <input type="file" id="cover" name="cover"
                           class="custom-file-input">
                    <label class="custom-file-label" for="cover">选择文件</label>
                </div>
            </div>
            <div class="col-sm-3 text-danger">
                <span th:if="${book != null}" th:errors="${book.cover}">错误提示</span>
            </div>
        </div>
        <div class="form-group row">
            <div class="col-sm-6 text-right">
                <button type="submit" class="btn btn-primary">添加</button>
            </div>
            <div class="col-sm-6">
                <button type="reset" class="btn btn-danger">重设</button>
            </div>
        </div>
    </form>
</div>

</body>
</html>

구성 파일:
파일 업로드를 위한 디렉터리를 설정합니다.
여기에 이미지 설명을 삽입하세요.

프런트 엔드에서 전송된 파일 데이터를 캡슐화하는 Book 개체를 만듭니다.
여기에 이미지 설명을 삽입하세요.

백엔드 비즈니스 로직 코드:

package cn.ljh.file_upload.controller;

import cn.ljh.file_upload.domain.Book;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.UUID;

@Controller
public class FileUpLoadController {
    
    

    //指定文件上传的存储路径,把路径写在配置文件中,通过 @Value 注解来获取该属性值
    @Value("${ljh.myfile.savePath}")
    private String destPath;

    @SneakyThrows
    @PostMapping("/addBookFile")
    public String addBookFile(Book book, Model model){
    
    
        //处理文件上传逻辑:也就是把文件内容保存到服务器的指定路径下。

        //创建文件
        File file = new File(destPath);
        //判断文件是否存在
        if (!file.exists()){
    
    
            //如果没有该文件,也就是该目录不存在,则创建该目录
            file.mkdir();
        }
        /*
         * destFile 是服务器端重新生成的一个文件名,而且保留了原来的拓展名。
         * 比如 我们上传文件的拓展名是 .jpg , 服务器生成的这个 destFile 文件,
         * 不仅要有上传的文件的内容,拓展名(后缀名)也要保持一致
         * Extension: 扩展    Original:起初的、原先的
         */

        //获取上传文件的原拓展名

        //获取上传文件的文件名
        String originalFilename = book.getCover().getOriginalFilename();
        //通过String工具类来获取这个文件名的扩展名
        String ext = StringUtils.getFilenameExtension(originalFilename);

        /*
         *   destPath + "/"  : 指定文件上传的路径 ,路径和文件名之间需要加一个斜杠 /
         *   UUID.randomUUID().toString() : 生成文件名
         *   "." + ext : 文件的扩展名(后缀名)
         */
        //生成一个新的文件
        File destFile = new File(destPath + "/" + UUID.randomUUID().toString() + "." + ext);
        
        //获取要上传文件的内容,返回是MultipartFile对象
        MultipartFile cover = book.getCover();
        //MultipartFile对象有一个方法 transferTo :可以将上传文件的内容写入到指定的文件destFile中。
        cover.transferTo(destFile);

        model.addAttribute("tip" , originalFilename + "文件上传成功!");
        
        return "uploadfile_success";
    }
}

파일을 업로드한 후 페이지로 돌아가기:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>上传成功</title>
    <!--  引入css样式,用 link 元素  ,  stylesheet 样式单 , .gz表示是打包的,但是springboot会自动解包 -->
    <!--  引入 Bootstrap 的 Web Jar 中的 CSS 样式  -->
    <link rel="stylesheet" th:href="@{'/webjars/bootstrap/css/bootstrap.min.css'}">
    <!--  jquery 放在 bootstrap 前面,因为 bootstrap 需要依赖到 jquery  -->
    <!--  引入 jQuery 的 Web Jar 中的 js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/jquery/jquery.min.js'}"></script>
    <!--  引入 Bootstrap 的 Web Jar 中的 js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/bootstrap/js/bootstrap.bundle.min.js'}"></script>
    <!--  引入 popper 的 Web Jar 中的 Js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/popper.js/umd/popper.min.js'}"></script>

</head>
<body>
<div class="container">
    <h4>文件上传成功</h4>
    <div class="text-primary" th:text="${tip}">提示</div>
</div>

</body>
</html>

효과:

여기에 이미지 설명을 삽입하세요.

파일 에코

▲ 파일 업로드 에코를 확인하시길 바랍니다

 能看到上传后文件的图片,

 (1)需要将服务器保存文件的所使用的文件名传回给视图页面。

 (2)还需要将保存文件的路径设置为Spring Boot的静态资源路径。
      添加额外的静态资源路径时,额外添加的磁盘最后必须要有一个斜杠结尾

코드 데모:

추가 조사가 진행 중이므로 이미지를 성공적으로 에코할 수 없습니다.

업로드 후 파일 이름을 반환하려면 매개변수를 캡슐화하는 객체에 fileName 속성을 추가하세요.
여기에 이미지 설명을 삽입하세요.

파일명을 분리하여 book 객체에 설정합니다.
여기에 이미지 설명을 삽입하세요.

추가 정적 리소스 경로를 추가하는 구성 클래스를 만들고, 프로젝트를 읽고 표시할 수 있도록 이미지의 디스크 경로를 정적 리소스 경로에 매핑합니다.
여기에 이미지 설명을 삽입하세요.
파일이 업로드된 후 페이지에서 에코된 코드에는 이 문장만 있습니다.
여기에 이미지 설명을 삽입하세요.

구성된 디스크 경로의 끝에 슬래시를 추가해야 합니다.
여기에 이미지 설명을 삽입하세요.

결과:
잘 안 됐어요.
여기에 이미지 설명을 삽입하세요.

모든 코드:

마지막으로 에코 코드가 추가됩니다(에코는 성공하지 못했으며 추가 조사가 진행 중입니다).

색인

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    <!--  引入css样式,用 link 元素  ,  stylesheet 样式单 , .gz表示是打包的,但是springboot会自动解包 -->
    <!--  引入 Bootstrap 的 Web Jar 中的 CSS 样式  -->
    <link rel="stylesheet" th:href="@{'/webjars/bootstrap/css/bootstrap.min.css'}">
    <!--  jquery 放在 bootstrap 前面,因为 bootstrap 需要依赖到 jquery  -->
    <!--  引入 jQuery 的 Web Jar 中的 js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/jquery/jquery.min.js'}"></script>
    <!--  引入 Bootstrap 的 Web Jar 中的 js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/bootstrap/js/bootstrap.bundle.min.js'}"></script>
    <!--  引入 popper 的 Web Jar 中的 Js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/popper.js/umd/popper.min.js'}"></script>
    <!--  引入文件上传的界面组件的js  -->
    <script type="text/javascript"
            th:src="@{'/webjars/bs-custom-file-input/dist/bs-custom-file-input.js'}"></script>
    <script>
        // <!-- 当整个页面加载完成的时候,就执行这个函数,保证这个函数是在页面加载完成后才执行初始化 -->
        // <!-- 初始化 custom file input 组件的 JS 脚本 -->
        $(function () {
    
    
            bsCustomFileInput.init();
        })
    </script>
</head>
<body>
<div class="container">
    <h4>添加图书</h4>
    <!-- 保证请求是以 multipart/form-data 格式提交请求
     不用这个格式,文件上传的数据都不会传到服务器 -->
    <form method="post" th:action="@{/addBookFile}" enctype="multipart/form-data">
        <div class="form-group row">
            <label for="name" class="col-sm-2 col-form-label">图书名:</label>
            <div class="col-sm-7">
                <input type="text" id="name" name="name"
                       class="form-control" placeholder="请输入图书名">
            </div>
            <div class="col-sm-3 text-danger">
                <span th:if="${book != null}" th:errors="${book.name}">错误提示</span>
            </div>
        </div>
        <div class="form-group row">
            <label for="cover" class="col-sm-2 col-form-label">图书封面:</label>
            <div class="col-sm-7">
                <!--  custom-file 用来保证页面比较好看  -->
                <div class="custom-file">
                    <input type="file" id="cover" name="cover"
                           class="custom-file-input">
                    <label class="custom-file-label" for="cover">选择文件</label>
                </div>
            </div>
            <div class="col-sm-3 text-danger">
                <span th:if="${book != null}" th:errors="${book.cover}">错误提示</span>
            </div>
        </div>
        <div class="form-group row">
            <div class="col-sm-6 text-right">
                <button type="submit" class="btn btn-primary">添加</button>
            </div>
            <div class="col-sm-6">
                <button type="reset" class="btn btn-danger">重设</button>
            </div>
        </div>
    </form>
</div>

</body>
</html>

uploadfile_success.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>上传成功</title>
    <!--  引入css样式,用 link 元素  ,  stylesheet 样式单 , .gz表示是打包的,但是springboot会自动解包 -->
    <!--  引入 Bootstrap 的 Web Jar 中的 CSS 样式  -->
    <link rel="stylesheet" th:href="@{'/webjars/bootstrap/css/bootstrap.min.css'}">
    <!--  jquery 放在 bootstrap 前面,因为 bootstrap 需要依赖到 jquery  -->
    <!--  引入 jQuery 的 Web Jar 中的 js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/jquery/jquery.min.js'}"></script>
    <!--  引入 Bootstrap 的 Web Jar 中的 js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/bootstrap/js/bootstrap.bundle.min.js'}"></script>
    <!--  引入 popper 的 Web Jar 中的 Js 脚本  -->
    <script type="text/javascript" th:src="@{'/webjars/popper.js/umd/popper.min.js'}"></script>

</head>
<body>
<div class="container">
    <h4>文件上传成功</h4>
    <div class="text-primary" th:text="${tip}">提示</div>

    <!--  文件上传后进行回显  -->
    <img th:src="@{'/uploads/' + ${book.fileName}}">

</div>

</body>
</html>

package cn.ljh.file_upload.domain;

import lombok.Data;
import org.springframework.web.multipart.MultipartFile;

@Data
public class Book {
    
    

    private Integer id;
    private String name;
    //用来封装前端传来的文件数据
    private MultipartFile cover;

    //用于封装上传之后的文件名
    private String fileName;
    
}

FileUpLoadController

package cn.ljh.file_upload.controller;

import cn.ljh.file_upload.domain.Book;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.UUID;

@Controller
public class FileUpLoadController {
    
    

    //指定文件上传的存储路径,把路径写在配置文件中,通过 @Value 注解来获取该属性值
    @Value("${ljh.myfile.savePath}")
    private String destPath;

    @SneakyThrows
    @PostMapping("/addBookFile")
    public String addBookFile(Book book, Model model){
    
    
        //处理文件上传逻辑:也就是把文件内容保存到服务器的指定路径下。

        //创建文件
        File file = new File(destPath);
        //判断文件是否存在
        if (!file.exists()){
    
    
            //如果没有该文件,也就是该目录不存在,则创建该目录
            file.mkdir();
        }
        /*
         * destFile 是服务器端重新生成的一个文件名,而且保留了原来的拓展名。
         * 比如 我们上传文件的拓展名是 .jpg , 服务器生成的这个 destFile 文件,
         * 不仅要有上传的文件的内容,拓展名(后缀名)也要保持一致
         * Extension: 扩展    Original:起初的、原先的
         */

        //获取上传文件的原拓展名

        //获取上传文件的文件名
        String originalFilename = book.getCover().getOriginalFilename();
        //通过String工具类来获取这个文件名的扩展名
        String ext = StringUtils.getFilenameExtension(originalFilename);

        /*
         *   destPath + "/"  : 指定文件上传的路径 ,路径和文件名之间需要加一个斜杠 /
         *   UUID.randomUUID().toString() : 生成文件名
         *   "." + ext : 文件的扩展名(后缀名)
         */
        //生成一个新的文件

        //生成文件名
        String fileName = UUID.randomUUID().toString() + "." + ext;

        File destFile = new File(destPath + "/" + fileName);

        //获取要上传文件的内容,返回是MultipartFile对象
        MultipartFile cover = book.getCover();
        //MultipartFile对象有一个方法 transferTo :可以将上传文件的内容写入到指定的文件destFile中。
        cover.transferTo(destFile);

        //文件上传成功后回显的名字
        book.setFileName(fileName);

        model.addAttribute("tip" , originalFilename + "文件上传成功!");

        return "uploadfile_success";
    }
}

파일업로드구성

package cn.ljh.file_upload.config;

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

//用于文件上传成功后的回显的处理类
@Configuration
public class FileUpLoadConfig implements WebMvcConfigurer {
    
    

    //指定文件上传的存储路径,把路径写在配置文件中,通过 @Value 注解来获取该属性值
    @Value("${ljh.myfile.savePath}")
    private String destPath;

    //重写这个方法,用于添加额外的静态资源路径
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    
    

        //将文件上传的destPath这个磁盘路径添加成静态资源路径,并映射到 /uploads/** 路径下。
        registry.addResourceHandler("/uploads/**")
                .addResourceLocations(destPath);
    }
}

application.yml

#指定文件上传后保存的路径
ljh:
  myfile:
    savePath: F:\myCode\crazyCode\SpringBoot\springboot07\uploads\


추천

출처blog.csdn.net/weixin_44411039/article/details/132603731