美文网首页
Spring MVC使用ResponseEntity

Spring MVC使用ResponseEntity

作者: 二十五_0415 | 来源:发表于2019-08-02 16:09 被阅读0次

    我们实现http文件下载,主要是在响应头中让Content-Disposition的值为attachment(意味着消息体应该被下载到本地;大多数浏览器会呈现一个“保存为”的对话框,将filename的值预填为下载后的文件名,假如它存在的话)

    之前我都是使用在下载的方法里注入HttpServletResponse,然后往response里写数据,然后设置Header中加入Content-Disposition

    今天刚好又需要写一个下载的功能,然而我不想注入什么HttpServletResponse,那样很不美观,从网上的资料了解到了ResponseEntity,从spring MVC的文档中了解到这个类就像@ResponseBody,但是多了响应头和状态码。刚好下载文件是需要设置响应头的,所以就用了这个。

    然而构造方法是这样的

    public ResponseEntity(T body, MultiValueMap<String, String> headers, HttpStatus status) {
            super(body, headers);
            Assert.notNull(status, "HttpStatus must not be null");
            this.status = status;
        }
    

    这个body能不能直接用File呢,答案是不能。我试着下载了一个txt文件,确实会下载一个文件,但是这个文件的内容是文件的路径。我猜估计是掉了File的toString方法。具体干了啥,感兴趣的可以看看AbstractMessageConverterMethodProcessorwriteWithMessageConverters,debug一遍就清楚了。

    不能直接用File,那该用什么呢,习惯性的在stackoverflow上搜了一下,有用Resource的,也有用Byte[]的。那么两者有啥区别呢。
    用Resource,你返回的时候还是依赖文件的,你的Controller在返回之后还要进行一系列的操作,如果在这之前文件被删了,那么下载下拉的文件就是损坏的。一开始我是这么干的

    try {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.valueOf("application/force-download"));
                headers.set("Content-Disposition", "attachment;fileName*=UTF-8''" + UriUtils.encode(file.getName(), "UTF-8"));
                return new ResponseEntity<Resource>(new FileSystemResource(file), headers, HttpStatus.OK);
            } finally {
                // 这里删除文件
            }
    

    这个finally会在return语句的计算之后返回之前执行。所以文件被写到响应之前就被删了。所以我决定采用这种方式

     try(FileInputStream fi = new FileInputStream(file)) {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.valueOf("application/force-download"));
                headers.set("Content-Disposition", "attachment;fileName*=UTF-8''" + UriUtils.encode(file.getName(), "UTF-8"));
                return new ResponseEntity<byte[]>(IOUtils.toByteArray(fi), headers, HttpStatus.OK);
            } finally {
                // 这里删除文件
            }
    

    文件流要关闭哟,希望大家都用try-with-resources,这都9102年了答应我不要在finally里面close然后又try-catch了,我实在看不下去了

    相关文章

      网友评论

          本文标题:Spring MVC使用ResponseEntity

          本文链接:https://www.haomeiwen.com/subject/yimldctx.html