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
相关产品推荐
相关产品推荐

