【问题标题】:How to return byte array as an in memory file in java spring boot?java - 如何在java spring boot中将字节数组作为内存文件返回?
【发布时间】:2019-05-20 11:08:35
【问题描述】:

我有一个字节数组作为数据。现在我如何编写一个控制器方法来使用 Spring Boot 将此字节数组作为文件返回?如果我用这个字节数组数据创建一个文件,那么我也应该注意删除它,对吗?

有没有办法将这个字节数组作为文件发送,而不必在我的项目中物理创建文件,也许通过网络或其他方式发送所有字节?

但是,如果这是不可能的,那么文件创建、在 rest api 中响应然后删除它是解决这个问题的唯一方法吗?我的控制器方法在 Spring Boot 中看起来像这样

@GetMapping("/download")
public ResponseEntity<Resource> download(String param) throws IOException {
    // Assume I already have this byte array from db or something
    Byte[] a = getItFromDB();

    // return it as a file without explicitly creating another file in my machine
    // I am ok with changing return type of this method from ResponseEntity to anything else if you have a solution
}

【问题讨论】:

  • 通常我们在 web 容器的 temp 和一个计划在 1 天后删除它们的 crontab 中创建这些文件...
  • 哦,好的。这就说得通了。但是为什么要在 1 天后删除呢?如果我们退回后立即删除呢?
  • 那是因为可能一个用户一天要多次下载一个文件,而且你应该等到下载完成然后你可以删除文件,所以你不知道客户端下载需要多少文件(互联网带宽...)

标签: java arrays spring file spring-boot


【解决方案1】:

我个人用 ResponseEntity 来做这样的事情


@GetMapping(path = "/downloadFile")
public ResponseEntity<?> downloadFile (){

    HttpHeaders headers = new HttpHeaders();
    headers.set("Content-type", MediaType.IMAGE_JPEG_VALUE);
    headers.set("Content-Disposition","attachment; filename=\"whaterver.jpg\"")); // to view in browser change attachment to inline 

    return ResponseEntity.status(HttpStatus.OK).headers(headers).body(byteArrayFile);
}

【讨论】:

    【解决方案2】:

    只需将byte[] 数组包装成ByteArrayResource (这是Resource 接口的实现), 从中构建一个ResponseEntity&lt;Resource&gt;,然后返回它。

    @GetMapping("/download")
    public ResponseEntity<Resource> download(String param) throws IOException {
        // Assume I already have this byte array from db or something
        byte[] array = getItFromDB();
    
        ByteArrayResource resource = new ByteArrayResource(array);
        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .contentLength(resource.contentLength())
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        ContentDisposition.attachment()
                            .filename("whatever")
                            .build().toString())
                .body(resource);
    }
    

    无需创建临时文件, 并且无需更改返回类型。

    Content-Type 标头中的媒体类型和文件名 Content-Disposition 标头中的重要提示 网络浏览器(或任何客户端)接收您的下载。 您可能应该使用比上面代码中的值更好的值。 例如:对于 PNG 图像内容,您将使用 MediaType.IMAGE_PNG"whatever.png"。然后是浏览器 可能会打开系统最喜欢的图像查看器。

    【讨论】:

    • 我很好奇为什么这个答案不被赞成或接受?它完全可以完成所要求的工作。
    【解决方案3】:

    这有什么问题?

    public byte[] download(String param) throws IOException {
        return whateverByteArrayContenHere;
    }
    

    【讨论】:

    • 我可以在前端下载这个文件吗?我的意思是这个字节[],我们没有指定任何关于文件名或其他文件元信息的内容,对吧?一般而言,将文件发送到前端或任何其他客户端的最佳做法是什么?
    • @theprogrammer 是的,它有效,您可以在响应标头中设置文件名,如下所示response.setHeader("Content-disposition", "attachment; filename="+ fileName);
    • 这一切都取决于前端的解释。从服务器的角度来看,这实际上并不重要。您所能做的就是设置额外的标题,这些标题可以“提示”前端的内容实际是什么(毕竟它可以是任何东西)。
    【解决方案4】:

    作为一种正常方式,我认为最好在 Web 容器中创建一个临时文件并将其作为文件发送给客户端。您还可以使用计划 crontab 根据您的策略清理临时文件。欲了解更多信息,请访问save temp fileclean temp

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-20
      • 2021-11-01
      • 2020-11-17
      • 2021-12-13
      • 2013-01-09
      • 2021-09-18
      • 2011-05-25
      • 1970-01-01
      相关资源
      最近更新 更多