【问题标题】:Stream the data content directly from database to the HTTP将数据内容直接从数据库流式传输到 HTTP
【发布时间】:2017-05-11 09:57:26
【问题描述】:
现在我们将文件保存在我们的 postgresql 数据库中,并使用我们实体中的byte[] 字段映射该内容。我需要调查我们是否可以
将内容数据直接从数据库流式传输到 HTTP 输出流,并以相反的方式执行相同的操作,使用 jpa Blob 数据类型将二进制数据从 HTTP 流式传输到数据库。我知道Blob 有方法getBinaryStream 和setBinaryStream 所以它可以工作,我们不需要将数据保存到内存中。
我关心的是数据库事务,因为我们将实体映射到 DTO,第二件事是 Http 请求中断,数据可能会在某些时候丢失。
有没有人对此解决方案有任何经验?
【问题讨论】:
标签:
spring
postgresql
jpa
spring-data-jpa
【解决方案1】:
从 BLOB 流式读取数据的解决方案:
现有的 BLOB 数据通过将 OutputStream(由 servlet 容器提供)传递到事务方法中进行流式传输,该方法将实体 blob 数据从内部事务写入流。请注意,响应的内容类型是在在写入数据之前设置的。
实体类:
public class Attachment {
private java.sql.Blob data;
public java.sql.Blob getData() { return data; }
}
服务方式:
@Transactional(readOnly = true)
public void copyContentsTo(long attachmentId, OutputStream outputStream) throws IOException {
Attachment dbAttachment = attachmentRepository.findOne(attachmentId);
try (InputStream is = dbAttachment.getData().getBinaryStream()) {
IOUtils.copy(is, outputStream);
} catch (SQLException e) {
throw new ParameterException("Cannot extract BLOB for attachment #" + attachmentId, e);
}
}
REST API Spring Controller 方法:
@GetMapping(value = "/api/project-attachment/{attachment-id}/content")
@ResponseStatus(HttpStatus.OK)
public void getAttachmentContent(
@PathVariable("attachment-id") long attachmentId,
HttpServletResponse response,
OutputStream stream) throws IOException {
response.setContentType(getMime(attachmentId));
attachmentService.copyContentsTo(attachmentId, stream);
}
【解决方案2】:
Lucasz, Spring Content for JPA 完全符合您的要求。旨在使创建处理内容(文档、图像、视频等)的 Spring 应用程序变得非常容易。它支持一系列后端存储,其中一个是关系数据库,显然它们使用 BLOB。
这个 JPA 模块会将上传的文件从请求输入流直接流式传输到数据库,反之亦然,因此它从不将整个文件存储在内存中,这显然会导致文件非常大的问题。
这将使您不必在@tequilacat 的答案中编写任何代码。
可能值得一看。