如何在WebRTC与libdatachannel中发送超大小限制的文件内容
解决libdatachannel发送大文件的消息大小超限问题
浏览器端WebRTC数据通道的默认消息大小限制(通常约64KB)无法修改,你需要手动将文件拆分为多个小分片发送,再在接收端重组。具体实现如下:
1. 发送端:拆分文件并分片发送
不再一次性将整个文件内容打包进JSON,而是先发送文件元数据,再分批次发送内容分片:
#include <fstream> #include <vector> #include <nlohmann/json.hpp> using json = nlohmann::json; // 分片大小设为60KB,留足余量避免触发浏览器限制 const size_t CHUNK_SIZE = 60 * 1024; void sendFile(std::shared_ptr<rtc::DataChannel> dc, const std::wstring& filePath) { // 读取文件内容 std::ifstream file(filePath, std::ios::binary | std::ios::ate); if (!file.is_open()) return; std::streamsize fileSize = file.tellg(); file.seekg(0, std::ios::beg); std::vector<char> fileBuffer(fileSize); if (!file.read(fileBuffer.data(), fileSize)) return; file.close(); // 发送元数据:告知接收端文件基本信息 json metadata = { {"Message_Type", "File_Metadata"}, {"FileName", filePath.substr(filePath.find_last_of(L"/\\") + 1)}, {"TotalSize", fileSize}, {"TotalChunks", (fileSize + CHUNK_SIZE - 1) / CHUNK_SIZE} // 向上取整计算分片数 }; dc->send(metadata.dump()); // 分片发送文件内容 for (size_t i = 0; i < fileBuffer.size(); i += CHUNK_SIZE) { size_t chunkLen = std::min(CHUNK_SIZE, fileBuffer.size() - i); std::string chunkData(fileBuffer.data() + i, chunkLen); json chunkMsg = { {"Message_Type", "File_Chunk"}, {"ChunkIndex", i / CHUNK_SIZE}, {"IsLastChunk", (i + chunkLen) >= fileBuffer.size()}, {"ChunkData", chunkData} }; dc->send(chunkMsg.dump()); } }
2. 接收端(浏览器JS):重组分片
监听数据通道的message事件,先接收元数据初始化缓存,待所有分片收齐后合并为完整文件:
let fileCache = {}; dataChannel.onmessage = (event) => { const msg = JSON.parse(event.data); switch(msg.Message_Type) { case "File_Metadata": // 初始化文件缓存 fileCache = { fileName: msg.FileName, totalSize: msg.TotalSize, totalChunks: msg.TotalChunks, receivedChunks: {}, receivedCount: 0 }; break; case "File_Chunk": if (!fileCache) return; // 存储当前分片 fileCache.receivedChunks[msg.ChunkIndex] = msg.ChunkData; fileCache.receivedCount++; // 检查是否所有分片已接收 if (fileCache.receivedCount === fileCache.totalChunks) { // 合并所有分片 let fileContent = ""; for (let i = 0; i < fileCache.totalChunks; i++) { fileContent += fileCache.receivedChunks[i]; } // 示例:将合并后的内容转为Blob并下载 const blob = new Blob([fileContent], {type: "application/octet-stream"}); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = fileCache.fileName; a.click(); URL.revokeObjectURL(url); // 清空缓存 fileCache = {}; } break; } };
注意事项
- 分片大小建议控制在60KB以内,适配不同浏览器的默认限制。
- 默认的可靠数据通道会自动保证分片的顺序和送达,若使用不可靠通道,需额外添加分片校验、重传逻辑。
- 大文件发送时可通过分片发送进度,实现整体传输进度提示。
内容的提问来源于stack exchange,提问作者rumeysa
相关产品推荐
相关产品推荐

