如何将二进制消息作为输入流处理?
Posted
技术标签:
【中文标题】如何将二进制消息作为输入流处理?【英文标题】:How to process binary messages as input streams? 【发布时间】:2019-10-15 13:06:59 【问题描述】:我想通过 WebSockets 实现大文件的上传,并让服务器将文件存储在数据库或对象存储中。
我正在试用spring-websocket
库,据我了解,我需要扩展BinaryWebSocketHandler
类并在那里实现文件存储。
public class MyWebSocketHandler extends BinaryWebSocketHandler
@Override
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception
// Store file in DB/OS...
虽然这看起来很棒,但我的问题是我要处理的 BinaryMessage
只允许我使用 ByteBuffer
s。我假设这意味着整个文件被加载到内存中并存储在这个ByteBuffer
对象中(当然,除非我也覆盖了supportsPartialMessages
方法)。这是正确的吗?
如果是,这对我来说将是一个大问题,因为我不想在内存中存储大文件。我期待能够访问InputStream
并从那里读取文件。看起来这应该是可能的,因为spring-websocket
在后台使用 Java WebSocket API,并且它们允许MessageHandler
s 处理InputStream
s(请参阅https://docs.oracle.com/javaee/7/api/javax/websocket/MessageHandler.Whole.html)。
不幸的是,我在我的处理程序中找不到任何访问InputStream
的方法。有谁知道这是否真的可能?如果不是,这作为功能请求是否有意义,或者这是否会以某种方式滥用 WebSockets?
【问题讨论】:
【参考方案1】:您可以覆盖AbstractWebSocketHandler.supportsPartialMessages
,它声明:
如果此标志设置为 true 并且底层 WebSocket 服务器支持部分消息,则可能会拆分大型 WebSocket 消息或未知大小的消息之一,并可能通过对 WebSocketHandler.handleMessage(WebSocketSession, WebSocketMessage) 的多次调用来接收。标志 WebSocketMessage.isLast() 指示消息是否为部分以及是否为最后部分。
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/socket/WebSocketHandler.html
【讨论】:
我知道部分消息,但如果我使用这些消息,将文件保存在数据库或对象存储中会变得更加困难。当我收到块 #1 时,我可以轻松地将其插入数据库,但是当它出现时我将如何附加块 #2?我不知道有任何与数据库无关的 SQL 语句可以让我这样做。这就是为什么我想使用InputStream
而不是字节数组。
您可能希望写入一个临时文件,而不是写入数据库,然后在isLast
上将该文件插入数据库。另请参阅:***.com/questions/37896551/… 一个我没有看到解决的问题是放弃转移。
我希望避免这种情况,因为我的应用程序在磁盘空间有限的容器中运行,因此如果同时触发大量上传,使用临时文件可能会导致崩溃。使用 Spring WebMVC 和 HTTP,我可以访问 InputStream
并将其直接传递给数据库。我希望 Web 套接字也能实现同样的目标,但显然情况并非如此。我将尝试在他们的 GitHub 页面中打开一个功能请求。也许是有原因的。感谢您向我指出相关问题。显然,其他人也对此感兴趣。
也许仅依靠 WebMVC / HTTP 进行此类上传是值得的,例如,通过套接字的消息可以“请求”一个端口和上传文件的权限,然后单独处理。通过链接这两者,您可以直接将 websocket 会话与文件相关联,并坚持使用 websocket 处理其他所有内容。
我实际上想要相反 - 使用 Web 套接字进行文件上传,使用 HTTP 进行其他所有操作。在请求到达我的应用程序之前,它会通过一个路由器应用程序(即 Cloud Foundry 的 GoRouter)。此路由器会终止在 15 分钟内未收到响应的每个请求,如果上传文件很大和/或用户的 Internet 连接速度较慢,则很容易发生这种情况。但是,路由器不会终止 Web 套接字通信(至少据我所知)。以上是关于如何将二进制消息作为输入流处理?的主要内容,如果未能解决你的问题,请参考以下文章