You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java WebSocket传输过大报TOO BIG,求解决及图片传输方案

解决Java WebSocket服务端接收大Base64图片时“TOO BIG”断开的问题

看起来你遇到的是WebSocket默认消息大小限制导致的断开——Base64编码会让图片体积膨胀约30%,很容易触发容器的默认大小阈值。下面给你两种解决方案,按需选择:

方案一:提升WebSocket的消息大小限制

因为你用的是Java EE标准的@ServerEndpoint,不同容器(Tomcat、Jetty等)的配置方式略有不同,这里以最常用的Tomcat为例:

代码级配置(推荐,无需修改容器配置)

自定义一个ServerEndpointConfig.Configurator来覆盖默认的消息大小限制:

public class CustomWsConfigurator extends ServerEndpointConfig.Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
        // 设置最大文本消息大小为10MB(Base64属于文本消息)
        config.getUserProperties().put("javax.websocket.maxTextMessageSize", 10 * 1024 * 1024);
        // 如果后续要支持二进制消息,也可以设置二进制消息的最大大小
        config.getUserProperties().put("javax.websocket.maxBinaryMessageSize", 10 * 1024 * 1024);
    }
}

然后在你的ChatEndpoint上指定这个配置类:

@ServerEndpoint(value = "/chat/{username}", 
                decoders = MessageDecoder.class, 
                encoders = MessageEncoder.class,
                configurator = CustomWsConfigurator.class) // 添加这一行
public class ChatEndpoint {
    // 原有的代码逻辑保持不变...
}

容器级配置(全局生效)

如果想让所有WebSocket端点都生效,可以修改Tomcat的web.xml,添加以下参数:

<context-param>
    <param-name>org.apache.tomcat.websocket.textBufferSize</param-name>
    <param-value>10485760</param-value> <!-- 10MB,单位字节 -->
</context-param>
<context-param>
    <param-name>org.apache.tomcat.websocket.binaryBufferSize</param-name>
    <param-value>10485760</param-value>
</context-param>

方案二:改用二进制直接传输图片(更优)

Base64编码不仅增加体积,还会带来额外的编码解码开销。直接发送图片的二进制数据是更高效的方案:

服务端修改

添加一个处理二进制消息的方法,同时调整消息对象支持图片类型:

@OnMessage
public void onBinaryMessage(Session session, byte[] imageBytes) throws IOException, EncodeException {
    // 从Session中获取发送方用户名
    String sender = (String) session.getUserProperties().get("username");
    
    // 构建图片消息对象(假设你的Message类有type、from、to、content等字段)
    Message imageMsg = new Message();
    imageMsg.setFrom(sender);
    imageMsg.setTo("全体用户"); // 根据你的业务逻辑指定接收方
    imageMsg.setType("image");
    // 可以将二进制转成Base64存到content,或者给Message类新增byte[]类型的字段
    imageMsg.setContent(Base64.getEncoder().encodeToString(imageBytes));
    
    // 广播图片消息给所有在线用户
    broadcast(imageMsg);
}

客户端修改

选择图片后直接读取二进制数据发送,同时处理接收的二进制消息:

// 给文件选择器添加监听(假设你有<input type="file" id="imagePicker" accept="image/*">)
document.getElementById("imagePicker").addEventListener("change", function(e) {
    const file = e.target.files[0];
    if (!file || !file.type.startsWith('image/')) return;
    
    const reader = new FileReader();
    reader.onload = function(event) {
        // 直接发送ArrayBuffer格式的二进制数据
        ws.send(event.target.result);
    };
    reader.readAsArrayBuffer(file);
});

// 修改onMessage处理二进制消息
ws.onmessage = function(event) {
    if (event.data instanceof Blob) {
        // 将二进制Blob转成可预览的URL
        const imgUrl = URL.createObjectURL(event.data);
        // 创建图片元素并添加到聊天窗口
        const img = document.createElement('img');
        img.src = imgUrl;
        img.style.maxWidth = "300px"; // 限制图片显示大小
        document.getElementById("chatWindow").appendChild(img);
    } else {
        // 原有的文本消息处理逻辑不变
        const msg = JSON.parse(event.data);
        // ... 你的文本消息渲染代码
    }
};

总结

  • 如果只是临时解决大Base64的问题,调整WebSocket消息大小限制即可;
  • 如果追求长期的性能和传输效率,强烈推荐改用二进制直接传输图片,这也是大多数聊天应用的主流方案。

内容的提问来源于stack exchange,提问作者Kata Vankee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:00:59