Spring Boot 2.x 实现文件上传与下载

x33g5p2x  于2021-11-09 转载在 Spring  
字(4.7k)|赞(0)|评价(0)|浏览(615)

前言

文件上传的功能是我们在网页中最为常见的功能,比如网盘文件上传,上传账号图像,Excel文件数据的导入功能等等,都需要通过IO流的方式进行上传和下载文件,本文讲解几种基于SpringBoot 2.x来实现文件上传与下载的操作。

文件上传

配置文件上传大小限制

spring.servlet.multipart.max-file-size=10GB
spring.servlet.multipart.max-request-size=10GB

创建文件上传页面

在resources目录下的templates中创建一个文件上传的页面upload.html,内容如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>文件上传页面</title>
</head>
<body>
<h1>文件上传页面</h1>
<form method="post" action="/fileupload" enctype="multipart/form-data">
    选择要上传的文件:<input type="file" name="file"><br>
    <hr>
    <input type="submit" value="提交">
</form>
</body>
</html>

页面效果:

创建文件上传Controller

创建文件上传的处理控制器,命名为FileController

/** * 文件上传与下载 */
@Controller
public class FileController {

    /** * 文件上传页面 * @return */
    @RequestMapping("/upload")
    public String file(){
        return "upload";
    }

    /** * 文件上传 * @param file * @return 上传信息 */
    @PostMapping("/fileupload")
    @ResponseBody
    public String fileUpload(@RequestPart MultipartFile file) {
        //获取文件原始名称含扩展名
        String fileName = file.getOriginalFilename();
        //定义文件存放位置
        String filePath = "H:\\AAA\\"+fileName;
        //将路径放入File实例
        File dest = new File(filePath);
        //获取文件大小(单位kb) getSize返回字节bit/1024/1024取MB做单位-->1048576=1024x1024
        float size = (((float)file.getSize())/1048576);
        //获取文件类
        String type = file.getContentType();
        //判断文件目录是否存在若不存在将进行创建
        if (!dest.exists()){
            //创建目录
            dest.mkdirs();
        }
        try {
            //将接收到的文件传输到给定的目标文件
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            //出现异常返回上传失败的信息
            return "Upload file success : 上传失败";
        }
            //上传成功返回文件存放路径
        return "Upload file success : 上传成功!文件存放路径为:"+dest.getAbsolutePath()
                +"\n文件大小:"+size+"MB"+"\n文件类型:"+type;
    }

}

文件上传主要用到的方法及参数:

  • MultipartFile:
    MultipartFile用作参数,用于接收用户上传的文件
  • transferTo()方法
    将接收到的文件传输到给定的目标文件,需要传入带有路径的File实例
  • getOriginalFilename()方法
    获取文件原始名称含扩展名
  • getSize()方法
    获取文件大小,默认单位:KB

演示文件上传效果

文件上传位置在H盘下AAA文件夹中

//定义文件存放位置
String filePath = "H:\\AAA\\"+fileName;

多个文件上传

上传页面

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>文件上传页面</title>
</head>
<body>
<h1>文件上传页面</h1>
<form method="post" action="/fileupload" enctype="multipart/form-data">
    文件1:<input type="file" name="files"><br>
    文件2:<input type="file" name="files"><br>
    <hr>
    <input type="submit" value="提交">
</form>
</body>
</html>

页面

Controller

/** * 多个文件上传 * @param files * @return 上传信息 */
    @PostMapping("/fileupload")
    @ResponseBody
    public String fileUpload(@RequestPart MultipartFile[] files) {
        //遍历文件
        for (MultipartFile file : files) {
            //获取文件原始名称含扩展名
            String fileName = file.getOriginalFilename();
            //定义文件存放位置
            String filePath = "H:\\AAA\\"+fileName;
            //将路径放入File实例
            File dest = new File(filePath);
            //判断文件目录是否存在若不存在将进行创建
            if (!dest.exists()){
                //创建目录
                dest.mkdirs();
            }
            try {
                //将接收到的文件传输到给定的目标文件
                file.transferTo(dest);
            } catch (IOException e) {
                e.printStackTrace();
                //出现异常返回上传失败的信息
                return "Upload file success : 上传失败";
            }
        }
        return "Upload file success : 成功上传"+files.length+"个文件";
    }

改动说明

  • MultipartFile使用数组,参数名称files对应html页面中input的name,一定要对应。
  • 后续处理文件的主体(for循环内)跟之前的一样,就是对MultipartFile数组通过循环遍历的方式对每个文件进行存储。

演示多个文件上传效果

文件下载

下载

@GetMapping("/download")
    public String downloadFile(HttpServletRequest request, HttpServletResponse response) {
        String fileName = "wallpaper.jpg";// 文件名
        if (fileName != null) {
            //设置文件路径
            File file = new File("H:\\AAA",fileName);
            if (file.exists()) {
                // 设置强制下载不打开
                response.setContentType("application/force-download");
                // 设置文件名
                response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
                byte[] buffer = new byte[1024];
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                try {
                    //文件输入流读取本地文件
                    fis = new FileInputStream(file);
                    //将文件输入流转成字节缓冲输入流
                    bis = new BufferedInputStream(fis);
                    //定义字节输出流
                    OutputStream os = response.getOutputStream();
                    //遍历输出字节流
                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer, 0, i);
                        i = bis.read(buffer);
                    }
                    return "下载成功";
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    //关闭字节缓冲输入流
                    if (bis != null) {
                        try {
                            bis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    //关闭文件输入流
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return "下载失败";
    }

演示效果

H盘中AAA文件夹下有一张图片

@GetMapping("/download")下载接口为:/download

图片正常无损下载

注意点

  • 设置强制下载不打开response.setContentType("application/force-download");
    如果不设置强制下载打开,当你在下载视频、音乐、图片等…浏览器不是第一时间下载,而是在网页直接给你预览出来了。

例如下载图片:

  • 设置文件名response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
    如果不设置文件名,在下载文件的时候会以接口名作为文件名称且没有扩展名。

如图:

更改接口名称为download1

如图

手动添加文件对应类型的扩展名即可正常打开

相关文章