欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringBoot的文件上传下载

程序员文章站 2022-03-04 21:02:52
...

1、项目结构

SpringBoot的文件上传下载
配置 application.properties

# 禁用缓存
spring.thymeleaf.cache=false

server.servlet.context-path=/file
# springboot2.2.x 默认不支持delete put等请求方式
# 必须在此处配置开启
spring.mvc.hiddenmethod.filter.enabled=true

# 开启 multipart 上传功能
spring.servlet.multipart.enabled=true
# 文件写入磁盘的阈值
spring.servlet.multipart.file-size-threshold=2KB
# 最大文件大小
spring.servlet.multipart.max-file-size=200MB
# 最大请求大小
spring.servlet.multipart.max-request-size=215MB

logging.level.root=info

2、java 类

这里注意,我的上传、下载路径是基于盘符的一个绝对路径。为了演示好,直接选择了项目所在的位置。

package org.feng.controller;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;


/**
 * Created by Feng on 2019/12/31 9:26
 * CurrentProject's name is spring-boot-learning
 * @author Feng
 */
@Controller
public class FileController {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileController.class);

    /**上传时保存文件的路径*/
    private final String SAVE_PATH = "D:/jee-2019-7-idea-maven-workspace/spring-boot-learning/spring-file/src/main/resources" +
            "/file/upload/";

    /**下载时目标文件的路径*/
    private final String DOWNLOAD_PATH = "D:/jee-2019-7-idea-maven-workspace/spring-boot-learning/spring-file/src/main/resources" +
            "/file/download/";
    /**
     * 去上传下载页面
     */
    @RequestMapping("/index")
    public String index() {
        return "/index";
    }


    /**
     * 上传单个文件
     * @param file {@link MultipartFile}
     * @return 成功页面
     */
    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file){
        if(file == null){
            throw new RuntimeException("MultipartFile is not define in page");
        }

        String fileName = file.getOriginalFilename();

        LOGGER.info("File name is " + fileName + ", save path is " + SAVE_PATH);

        String suffix = fileName.substring(Objects.requireNonNull(fileName).lastIndexOf("."));

        File dest = new File(SAVE_PATH + "/" + System.currentTimeMillis() + suffix);

        try {
            file.transferTo(dest);
            LOGGER.info("File is upload over");
        } catch (IOException e) {
            LOGGER.error("File upload error", e);
        }

        return "success";
    }


    /**
     * 上传多个文件
     * @param request 内部请求对象
     * @return 成功页面
     */
    @PostMapping("/uploadMore")
    public String uploadMore(HttpServletRequest request){
        List<MultipartFile> files = ((MultipartHttpServletRequest)request).getFiles("file");

        if(files.isEmpty()){
            throw new RuntimeException("MultipartFile is not define in page");
        }

        try {
            for (MultipartFile file : files) {
                String fileName = file.getOriginalFilename();
                String suffix = fileName.substring(Objects.requireNonNull(fileName).lastIndexOf("."));

                File dest = new File(SAVE_PATH + "/" + System.currentTimeMillis() + suffix);

                file.transferTo(dest);
            }
            LOGGER.info("File list is upload over");
        } catch (IOException e) {
            LOGGER.error("File upload error", e);
        }

        return "success";
    }

    /**
     * 下载文件
     * @param response 响应对象;用于设置响应参数
     * @param fileName 文件名
     * @throws IOException 文件操作
     */
    @GetMapping("/download")
    public ResponseEntity<byte[]> download(HttpServletResponse response,
                           @RequestParam("fileName") String fileName) throws IOException {

        File file = new File(DOWNLOAD_PATH + File.separator + fileName);
        HttpHeaders headers = new HttpHeaders();
        // 下载显示的文件名,解决中文名称乱码问题
        String downloadFileName;
        downloadFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
        // 弹出保存框即资源选择器
        response.setHeader("Content-Disposition","attachment;filename=" + downloadFileName);

        // application/octet-stream二进制流数据(文本下载)。
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<>(FileUtils.readFileToByteArray(file),
                headers, HttpStatus.CREATED);
    }
}

3、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 https://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.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.feng</groupId>
    <artifactId>spring-file</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-file</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--上传下载的依赖-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>4.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

4、页面

4.1 index.html 文件

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>上传、下载页面</title>

    <link th:href="@{/webjars/bootstrap/4.3.1/css/bootstrap.min.css}" rel="stylesheet">
</head>
<body>
    <p>单文件上传</p>
    <!--
    样式来源:
        https://blog.csdn.net/qq_39926957/article/details/83991902
    -->
    <form class="form-group" th:action="@{/upload}" method="POST" enctype="multipart/form-data">
        <div class="form-group">
            <div class="col-sm-6">
                <div class="input-group">
                    <label for='location'>选择文件&nbsp;&nbsp;</label><input id='location' class="form-control"
                                                          onclick="$('#i-file').click();">
                    <label class="input-group-btn">
                        <input type="button" id="i-check" value="浏览文件" class="btn btn-primary" onclick="$('#i-file').click();">
                    </label>
                </div>
            </div>
            <input type="file" name="file" id='i-file'  accept=".xls, .xlsx, .png, .txt, .*"
                   onchange="$('#location').val($('#i-file').val());" style="display: none">
        </div>
        <input class="btn btn-success" type="submit" value="上传">
    </form>

    <p>多文件上传</p>
    <form th:action="@{/uploadMore}" method="POST" enctype="multipart/form-data">
        <p>文件1:<input type="file" name="file"/></p>
        <p>文件2:<input type="file" name="file"/></p>
        <p><input type="submit" value="上传"/></p>
    </form>

    <p>文件下载</p>
    <a th:href="@{/download(fileName='1577760539482.png')}">下载</a>
</body>
<script type="text/javascript" th:src="@{/webjars/jquery/3.4.1/jquery.min.js}"></script>
<script type="text/javascript" th:src="@{/webjars/bootstrap/4.3.1/js/bootstrap.min.js}"></script>
</html>

4.2 success.html 文件

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>成功</title>
</head>
<body>
<a th:href="@{/index}">去上传下载页面</a>
</body>
</html>

5、测试

5.1 上传

SpringBoot的文件上传下载
SpringBoot的文件上传下载
SpringBoot的文件上传下载
SpringBoot的文件上传下载

5.2 多文件上传

5.3 下载

SpringBoot的文件上传下载
SpringBoot的文件上传下载