SpringBoot的文件上传下载

1、项目结构

在这里插入图片描述
配置 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 上传

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.2 多文件上传

5.3 下载

在这里插入图片描述
在这里插入图片描述

发布了108 篇原创文章 · 获赞 117 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/FBB360JAVA/article/details/103781147