小小白学Springboot(九)——文件的上传和下载

文件上传

一个简单的文件上传页面,点击添加文件,显示选择文件按钮,可上传多个文件

前端代码
upload.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
    <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
    <script th:src="@{/js/jquery-3.4.1.js}"  type="text/javascript"></script>
</head>
<style>
    form{
        margin: 20px;
    }
    .form-group{
        margin-top: 10px;

    }
    .btn-default{
        display: none;
    }
</style>
<body>
	<div th:if="${uploadStatues}" th:text="${uploadStatues}">上传成功</div>
	  <!-- uploadStatues 为上传成功还是失败的标志,在后端写的 -->
    <form th:action="@{/uploadFile}" method="post" enctype="multipart/form-data">
        <!-- @{/uploadFile} 为表单处理数据的后端-->  
        上传文件
        <input type="button" value="添加文件" id="add">

        <div id="abc">

        </div>
        <button type="submit" class="btn btn-default">提交</button>
    </form>
</body>
</html>

<script>
    $("#add").click(function (){
        var add = "<div class=\"form-group\">\n" +
            "            <input type=\"file\" name='upload'>\n" +
            "        </div>";
        $("#abc").append(add);
        $(".btn-default").css("display","block");
    })

</script>

然后就是控制类了,首先要有一个访问页面的Mapping

  @GetMapping("/upload")
    public String Upload() {
        return "upload";
    }

因为表单提交后,要处理表单数据,action的值为url,所以还需要一个处理表单数据的Mapping ,因为表单method设置为post,所以需要一个PostMapping,接收post数据

    @PostMapping("/uploadFile")
    public String uploadFile(MultipartFile upload[], Model model) {
    // upload[] 是 上传文件的name 通过name接收文件信息,为一个数组是因为传了多个文件
        model.addAttribute("uploadStatues", "上传成功!");
        for (MultipartFile file : upload) {
            String fileName = file.getOriginalFilename();   // 获取原文件的名称
            fileName = UUID.randomUUID() + "_" + fileName;  
            // 将原文件重新用UUID命名,避免重复,也可以用时间戳
            String mkdir = "E:/spring_upload/";   // 上传的文件应该存放的路径
            File filepath = new File(mkdir);
            if (!filepath.exists()) {
                filepath.mkdirs();
            }  // 如果路径不存在,建立该路径
            try {
                file.transferTo(new File(mkdir + fileName)); 
            } catch (IOException e) {
                e.printStackTrace();
                model.addAttribute("uploadStatues", "上传失败!" + e.getMessage());
            }
            // 上传文件 抛出异常,如果失败返回失败代码
        }
        return "upload";
    }

将上传成功与否的标志uploadStatues传回到原页面,所以 return “upload”,也可根据业务逻辑return至别的页面

测试结果

我们上传这三张图片
在这里插入图片描述
在这里插入图片描述
最后在E:/spring_upload下发现有这三张图片

最后虽然返回了upload,但访问路径仍为 uplodFile ,是 Spring Boot 中的转发方式,域发生改变但路径不变
重定向方式可以改变最后的访问路径

文件下载

我们只需要写一个代码告诉浏览器我现在要下载,然后弹出浏览器自带的下载框就行了

添加依赖

<dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
</dependency>

下载页面前端代码(down.html)

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>下载文件</title>
</head>
<body>
    <div>文件下载</div>
    <a th:href="@{/download(filename='刘昊然jpg')}">下载</a>
</body>
</html>

在这里插入图片描述
就这么简单的前端,大家理解下载的精髓就好了,这个不重要

单击下载,是一个a标签 会跳转到一个链接,所以我们需要两个控制类
一个用于访问down.html页面
一个用于a标签的跳转并处理下载

访问down.html页面控制类:

 @GetMapping("/todownload")
    public String download() {
        return "down";
    }

a标签的跳转控制类:

	 @GetMapping("/download")
    public ResponseEntity<byte[]> fileDownload(HttpServletRequest request,String filename) {
        String mkdir = "E:/springboot/images";
        File file = new File(mkdir+File.separator + filename);
        /* File.separator 可代表任意系统下的文件分隔符,如果考虑跨平台,最好写成
		File file = new File("E:" + File.separator + "springboot" + File.separator+"images"+filename);
		*/

        HttpHeaders headers = new HttpHeaders();
        headers.setContentDispositionFormData("attachment", filename);
		// 通知浏览器以下载文件的方式打开 下载名称默认为 filename
		
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		// 以流的形式下载

        try {
            return new ResponseEntity<>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK);
            // 返回文件
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseEntity<byte[]>(e.getMessage().getBytes(), HttpStatus.EXPECTATION_FAILED);
            //  失败 返回异常
        }
    }

如果下载文件的路径中有中文,要进行编码

在上面那个方法中加入

try {
            filename= getFilename(request,filename);
        } catch (Exception e) {
            e.printStackTrace();
        }

在这里插入图片描述

getFilename方法:

 private String getFilename(HttpServletRequest request,String filename)
            throws Exception {
        String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};
        String userAgent = request.getHeader("User-Agent");
        for (String keyWord : IEBrowserKeyWords) {
            if (userAgent.contains(keyWord)) {
                return URLEncoder.encode(filename, "UTF-8").replace("+"," ");
            }
        }
        return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
        }
File file = new File(mkdir+File.separator + filename);

File里面的参数是要下载文件的路径,filename 是a标签内传来的参数。

通常情况下载文件的文件名都是一个名称,而不是一个路径,所以我们将路径分成 路径+filename 的形式,便于 setContentDispositionFormData 的操作
将a标签内传参写成路径也没有问题,就是路径中的: / 在下载文件的默认名称中变成 _
像这样
在这里插入图片描述

运行结果:

在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值