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

如何在Socket.IO聊天应用中实现服务端向客户端发送图片?

实现Socket.IO聊天应用的图片发送功能

核心思路

将图片转换为Base64编码字符串(适配小型图片的聊天场景),与文本消息统一通过Socket.IO传输,服务端负责转发带类型标识的消息对象,客户端根据消息类型渲染对应内容。


1. 服务端代码修改

只需转发完整的消息对象,无需额外处理图片逻辑:

io.on("connection", (socket) => {
  socket.on("message", (msg) => {
    io.emit("message", msg);
  });
});

server.listen(4000, function () {
  console.log("listening on port 4000");
});

2. 客户端代码修改

2.1 补充状态管理

新增图片相关状态(以React useState为例):

const [state, setState] = useState({
  message: "",
  name: "你的昵称", // 替换为实际用户昵称逻辑
  image: "", // 存储图片的Base64编码
  messages: [] // 存储所有聊天消息
});
const { message, name, image, messages } = state;

const onTextChange = (e) => {
  setState(prev => ({ ...prev, message: e.target.value }));
};

const setImage = (base64) => {
  setState(prev => ({ ...prev, image: base64 }));
};

2.2 处理图片选择事件

给文件输入框添加onChange事件,将选中图片转为Base64:

<input 
  type="file" 
  accept="image/*" 
  onChange={(e) => {
    const file = e.target.files[0];
    if (!file) return;
    
    const reader = new FileReader();
    reader.onload = (event) => {
      setImage(event.target.result);
    };
    reader.readAsDataURL(file);
  }}
/>

2.3 修改消息提交逻辑

提交时区分文本/图片类型,发送带标识的消息对象:

const onMessageSubmit = (e) => {
  e.preventDefault();
  
  if (!message.trim() && !image) return;
  
  socket.emit("message", {
    name,
    type: image ? "image" : "text",
    content: image || message
  });
  
  // 清空输入状态
  setState(prev => ({
    ...prev,
    message: "",
    image: ""
  }));
  e.target.querySelector('input[type="file"]').value = "";
};

2.4 渲染聊天记录

根据消息类型渲染文本或图片:

const renderChat = () => {
  return messages.map((msg, idx) => (
    <div key={idx} className="chat-item">
      <span className="sender-name">{msg.name}:</span>
      {msg.type === "text" ? (
        <span className="text-message">{msg.content}</span>
      ) : (
        <img 
          src={msg.content} 
          alt="聊天图片" 
          style={{ maxWidth: "300px", borderRadius: "8px" }}
        />
      )}
    </div>
  ));
};

2.5 监听服务端消息

在组件挂载时监听消息并更新本地列表:

useEffect(() => {
  socket.on("message", (newMsg) => {
    setState(prev => ({
      ...prev,
      messages: [...prev.messages, newMsg]
    }));
  });
  
  return () => socket.off("message");
}, [socket]);

2.6 最终客户端返回部分代码

return (
  <>
    <h1>Chat With Your Doctor Now</h1>
    <div className="box">
      <form onSubmit={onMessageSubmit}>
        <h1>Message Section</h1>
        <div>
          <input
            name="message"
            onChange={onTextChange}
            value={message}
            id="outlined-multiline-static"
            variant="outlined"
            label="Message"
          />
        </div>
        <div>
          <input 
            type="file" 
            accept="image/*" 
            onChange={(e) => {
              const file = e.target.files[0];
              if (!file) return;
              
              const reader = new FileReader();
              reader.onload = (event) => {
                setImage(event.target.result);
              };
              reader.readAsDataURL(file);
            }}
          />
        </div>
        <button>Send Message</button>
      </form>
      <div className="render-chat">
        <h1>Conversation</h1>
        {renderChat()}
      </div>
    </div>
  </>
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 06:13:35