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

如何基于Socket.io与React扩展聊天应用支持PDF、视频等多类型文件传输?

实现Socket.io+React聊天应用的多类型文件发送与接收

当前代码仅支持图片传输,要扩展到PDF、视频等文件,核心是在传输时携带文件的MIME类型、文件名信息,客户端根据类型做差异化展示/处理,服务端只需转发完整的文件信息对象即可。

修改后的服务端代码

服务端无需复杂逻辑,仅需转发包含完整文件信息的对象:

// index.js
const express = require('express');
const app = express();
const PORT = 8080;
const http = require('http').createServer(app);
const cors = require('cors');
const io = require('socket.io')(http, {
    cors: {
        origin: ["http://localhost:3001"]
    }
});

io.on('connection', (socket) => {
    console.log(`⚡: ${socket.id} user just connected!`);

    // 接收完整文件信息对象并广播给所有客户端
    socket.on('fileUpload', (fileData) => {
        io.emit('fileUploadResponse', fileData);
    })
});

http.listen(PORT, () => {
    console.log(`Server listening on ${PORT}`);
});

修改后的客户端代码

重构状态管理以支持多文件消息,同时处理不同类型文件的读取与展示:

import React, { useEffect, useState } from 'react';

const ChatBody = ({ socket }) => {
    const [selectedFile, setSelectedFile] = useState(null);
    // 存储所有文件消息,每个消息包含文件名、MIME类型、Base64编码
    const [fileMessages, setFileMessages] = useState([]);

    useEffect(() => {
        socket.on("fileUploadResponse", (fileData) => {
            // 将新收到的文件消息添加到列表
            setFileMessages(prev => [...prev, fileData]);
        })
    }, [socket])

    // 读取文件为Base64格式(去掉data:xxx;base64,前缀)
    const readFileAsBase64 = (file) => {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = () => resolve(reader.result.split(',')[1]);
            reader.onerror = reject;
            reader.readAsDataURL(file);
        });
    };

    const handleFileChange = (e) => {
        setSelectedFile(e.target.files[0]);
    };

    const handleFileUpload = async () => {
        if (!selectedFile) return;
        const base64Data = await readFileAsBase64(selectedFile);
        // 构造包含完整信息的文件对象
        const fileData = {
            name: selectedFile.name,
            type: selectedFile.type,
            base64: base64Data
        };
        socket.emit('fileUpload', fileData);
        // 清空已选择的文件
        setSelectedFile(null);
    };

    // 根据文件类型渲染对应的展示组件
    const renderFileMessage = (msg) => {
        const dataUrl = `data:${msg.type};base64,${msg.base64}`;
        if (msg.type.startsWith('image/')) {
            return <img 
                style={{ width: '150px', height: 'auto', margin: '8px 0' }} 
                src={dataUrl} 
                alt={msg.name} 
            />;
        } else if (msg.type === 'application/pdf') {
            return <embed
                style={{ width: '300px', height: '400px', margin: '8px 0' }}
                src={dataUrl}
                type="application/pdf"
                title={msg.name}
            />;
        } else if (msg.type.startsWith('video/')) {
            return <video
                style={{ width: '300px', margin: '8px 0' }}
                controls
                src={dataUrl}
                title={msg.name}
            />;
        } else {
            // 其他类型文件提供下载链接
            return <a 
                style={{ display: 'block', margin: '8px 0' }}
                href={dataUrl} 
                download={msg.name}
            >
                下载文件: {msg.name}
            </a>;
        }
    };

    return (
        <div style={{ padding: '16px' }}>
            {/* 展示历史文件消息 */}
            <div className="file-messages">
                {fileMessages.map((msg, index) => (
                    <div key={index} className="file-message">
                        {renderFileMessage(msg)}
                    </div>
                ))}
            </div>
            {/* 文件上传区域 */}
            <div style={{ marginTop: '16px' }}>
                <input type="file" onChange={handleFileChange} disabled={!!selectedFile} />
                <button onClick={handleFileUpload} disabled={!selectedFile}>上传文件</button>
            </div>
        </div>
    );
};

export default ChatBody;

关键实现说明

  • 文件信息完整性:客户端将文件名、MIME类型、Base64编码打包发送,确保服务端转发后客户端能准确识别文件类型
  • 差异化渲染:通过msg.type判断文件类型,分别用img、embed、video标签支持预览,非预览类型提供下载链接
  • Base64优化:读取文件时去掉data:xxx;base64,前缀,减少传输的数据量
  • 多消息管理:用数组存储所有文件消息,支持连续发送多文件的展示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 07:34:58