【问题标题】:Can I use InputStreamResource to return an image as ByteArray into a Spring application?我可以使用 InputStreamResource 将图像作为 ByteArray 返回到 Spring 应用程序吗?
【发布时间】:2017-03-27 07:47:40
【问题描述】:

我正在开发一个 Spring Boot 后端应用程序。

我必须从数据库中的 BLOB 字段中检索 jpg 图像并将其返回到前端。

在线搜索我找到了有关控制器应如何返回文件以显示的教程:http://www.leveluplunch.com/java/tutorials/032-return-file-from-spring-rest-webservice/

正如您在上一个教程中看到的,它执行以下操作:

@RequestMapping(value = "/", method = RequestMethod.GET, produces = "application/pdf")
public ResponseEntity<InputStreamResource> downloadPDFFile()
        throws IOException {

    ClassPathResource pdfFile = new ClassPathResource("pdf-sample.pdf");

    return ResponseEntity
            .ok()
            .contentLength(pdfFile.contentLength())
            .contentType(
                    MediaType.parseMediaType("application/octet-stream"))
            .body(new InputStreamResource(pdfFile.getInputStream()));
}

因此,它返回了一个包装在 ResponseEntity 中的 InputStreamResource 对象。

过去我使用标准的 Java 字节数组。阅读文档我发现 InputStreamResource 是一个特定的 Spring 对象:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/InputStreamResource.html

所以,据我了解,我有标准的 Java InputStream 类型,它是一个抽象类,它是表示字节输入流的所有类的超类(就像我过去做过)。那么 InputStreamResource(在上一教程中使用)是 InputStream 的特定 Resource 实现。

阅读文档 Resource 是一个 Spring 接口,用于描述任何类型的资源(如图像、文件等)。

所以我怀疑这个 InputStreamResource 是否是将 JPEG 文件 作为字节数组返回到我的前端应用程序的正确选择?

我有这个疑问是因为在我阅读的官方文档中:

仅应在没有其他特定资源实现的情况下使用 适用的。特别是,更喜欢 ByteArrayResource 或任何 尽可能基于文件的资源实现。

这是一个好的解决方案吗?

【问题讨论】:

  • 根据文档,如果读取是单次使用,则可以使用一个 InputStreamResource。干杯。
  • “一次性”是什么意思?

标签: spring spring-mvc spring-boot


【解决方案1】:

一般来说,将结果回客户端是个好主意。原因很简单,图像和附件越来越大。当您返回一个字节数组时,您必须一次将所有这些字节保存在内存中。如果您发送的图像或附件太大而无法立即存储在内存中,这会将您引入意外的拒绝服务事件。

一般准则:

  • 如果有更好的资源类型,请使用它。在您的情况下,您可以在响应实体中返回您的 ClassPathResource
  • 还有一个 FileSystemResource 用于返回磁盘上的文件
  • 如果还没有其他资源类型,请使用InputStreamResource。示例正在返回 blob 内容

InputStreamResource的使用示例:

    return new InputStreamResource(blob.getPayload().openStream()) {
        @Override
        public long contentLength() {
            return blob.getMetadata().getContentMetadata().getContentLength();
        }
    };

我会告诫不要懒惰地考虑返回一个字节数组。仅当您的响应大小约为 1MB 或更少时才应考虑。

【讨论】:

  • Blob 字段不同。 Blob 是在事务端关闭的 JDBC 资源。由于流式传输内容是在事务结束后发生的,因此 jdbc-stream 已关闭,除了 IOException(或分别返回 SQLException)之外没有返回任何其他内容。
  • Spring Infrastructure 支持处理该问题——但是在您的情况下,您可能需要创建一个扩展 InputStreamResource 的实际对象,以关闭流、响应和连接对象,具体取决于您的数据库供应商.并非所有数据库供应商在这里都是平等的。
  • 你误会了。在线程离开 downloadPDFFile 方法之前,所有字节必须已经传输到浏览器! AFAIK 这在春天是不可能的!为了避免使用 byte[]-buffer 和切入点,我发现的唯一方法是使用 ServletResponse 的输出流。我应该构建一个提出问题的 Github 项目吗?
  • 可能。我知道上面的代码适用于我们的案例。
猜你喜欢
  • 2016-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-25
  • 2016-11-04
  • 2021-09-03
相关资源
最近更新 更多