gpt4 book ai didi

java - Spring Stomp over Websocket : Stream large files

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:05:43 24 4
gpt4 key购买 nike

网页中我的SockJs客户端,发送帧大小为16K的消息。邮件大小限制决定了我可以传输的文件的最大大小。

下面是我在文档中找到的内容。

/**
* Configure the maximum size for an incoming sub-protocol message.
* For example a STOMP message may be received as multiple WebSocket messages
* or multiple HTTP POST requests when SockJS fallback options are in use.
*
* <p>In theory a WebSocket message can be almost unlimited in size.
* In practice WebSocket servers impose limits on incoming message size.
* STOMP clients for example tend to split large messages around 16K
* boundaries. Therefore a server must be able to buffer partial content
* and decode when enough data is received. Use this property to configure
* the max size of the buffer to use.
*
* <p>The default value is 64K (i.e. 64 * 1024).
*
* <p><strong>NOTE</strong> that the current version 1.2 of the STOMP spec
* does not specifically discuss how to send STOMP messages over WebSocket.
* Version 2 of the spec will but in the mean time existing client libraries
* have already established a practice that servers must handle.
*/
public WebSocketTransportRegistration setMessageSizeLimit(int messageSizeLimit) {
this.messageSizeLimit = messageSizeLimit;
return this;
}

我的问题:我可以设置部分消息传递,以便一个文件被部分传输,而不是像现在这样作为单个消息传输吗?

更新:仍在寻找具有部分消息传递的解决方案同时现在对大消息使用 HTTP(在我的应用程序中是文件上传/下载)。

最佳答案

Can I setup a partial messaging so that a file is transferred part by part and is not getting transferred as a single message as it is been done now?

是的。这是我的 Spring boot 实验项目中的相关配置 - 基本上 UploadWSHandler 已注册并设置了 WebSocketTransportRegistration.setMessageSizeLimit

@Configuration
@EnableWebSocket
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new UploadWSHandler(), "/binary");
}

@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(50 * 1024 * 1024);
}
}

UploadWShandler 如下。抱歉这里的代码太多了——要点

  • supportsPartialMessage 返回 true。
  • handleBinaryMessage 将使用部分消息多次调用,因此我们需要组装字节。因此 afterConnectionEstablished 使用 websocket URL 查询建立身份。但您不必使用此机制。我选择这种机制的原因是为了保持客户端简单,以便我只调用一次 webSocket.send(files[0]),即我不会在 javascript 端对文件 blob 对象进行切片。 (要点:我想在客户端使用普通的 websocket - 没有 stomp/socks)
  • 内部客户端分块机制提供message.isLast()最后一条消息
  • 出于演示目的,我将其写入文件系统并使用 FileUploadInFlight 在内存中累积这些字节,但您不必执行此操作,并且可以在进行时流式传输到其他地方。
public class UploadWSHandler extends BinaryWebSocketHandler {

Map<WebSocketSession, FileUploadInFlight> sessionToFileMap = new WeakHashMap<>();

@Override
public boolean supportsPartialMessages() {
return true;
}

@Override
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
ByteBuffer payload = message.getPayload();
FileUploadInFlight inflightUpload = sessionToFileMap.get(session);
if (inflightUpload == null) {
throw new IllegalStateException("This is not expected");
}
inflightUpload.append(payload);

if (message.isLast()) {
Path basePath = Paths.get(".", "uploads", UUID.randomUUID().toString());
Files.createDirectories(basePath);
FileChannel channel = new FileOutputStream(
Paths.get(basePath.toString() ,inflightUpload.name).toFile(), false).getChannel();
channel.write(ByteBuffer.wrap(inflightUpload.bos.toByteArray()));
channel.close();
session.sendMessage(new TextMessage("UPLOAD "+inflightUpload.name));
session.close();
sessionToFileMap.remove(session);
}
String response = "Upload Chunk: size "+ payload.array().length;
System.out.println(response);

}

@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
sessionToFileMap.put(session, new FileUploadInFlight(session));
}

static class FileUploadInFlight {
String name;
String uniqueUploadId;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
/**
* Fragile constructor - beware not prod ready
* @param session
*/
FileUploadInFlight(WebSocketSession session) {
String query = session.getUri().getQuery();
String uploadSessionIdBase64 = query.split("=")[1];
String uploadSessionId = new String(Base64Utils.decodeUrlSafe(uploadSessionIdBase64.getBytes()));
System.out.println(uploadSessionId);
List<String> sessionIdentifiers = Splitter.on("\\").splitToList(uploadSessionId);
String uniqueUploadId = session.getRemoteAddress().toString()+sessionIdentifiers.get(0);
String fileName = sessionIdentifiers.get(1);
this.name = fileName;
this.uniqueUploadId = uniqueUploadId;
}
public void append(ByteBuffer byteBuffer) throws IOException{
bos.write(byteBuffer.array());
}
}
}

顺便说一句,一个工作项目也是sprint-boot-with-websocked-chunking-assembly-and-fetchwith-websocked-chunking-assembly-and-fetch 分支

关于java - Spring Stomp over Websocket : Stream large files,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37896551/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com