
我们希望实现一个零思想的文件传输机制,即在两个设备或个人之间共享文件,不需要考虑如何、在哪里、为什么和什么。
“WebRTC是一个免费的开放项目,通过简单的APIs为浏览器与移动应用程序提供实时通信(RTC)功能。WebRTC组件已经进行了优化,以更好地满足这一目的。” webrtc.org


const express = require("express");const http = require("http");const app = express();const server = http.createServer(app);const socket = require("socket.io");const io = socket(server);const users = {};const socketToRoom = {};io.on('connection', socket => {socket.on("join room", roomID => {if (users[roomID]) {const length = users[roomID].length;if (length === 2) {socket.emit("room full");return;}users[roomID].push(socket.id);} else {users[roomID] = [socket.id];}socketToRoom[socket.id] = roomID;const usersInThisRoom = users[roomID].filter(id => id !== socket.id);socket.emit("all users", usersInThisRoom);});socket.on("sending signal", payload => {io.to(payload.userToSignal).emit('user joined', { signal: payload.signal, callerID: payload.callerID });});socket.on("returning signal", payload => {io.to(payload.callerID).emit('receiving returned signal', { signal: payload.signal, id: socket.id });});socket.on('disconnect', () => {const roomID = socketToRoom[socket.id];let room = users[roomID];if (room) {room = room.filter(id => id !== socket.id);users[roomID] = room;socket.broadcast.emit('user left', socket.id);}});});server.listen(process.env.PORT || 8000, () => console.log('server is running on port 8000'));
import React, { useEffect, useRef, useState } from "react";import io from "socket.io-client";import Peer from "simple-peer";import styled from "styled-components";import streamSaver from "streamsaver";const Container = styled.div`padding: 20px;display: flex;height: 100vh;width: 90%;margin: auto;flex-wrap: wrap;`;const worker = new Worker("../worker.js");const Room = (props) => {const [connectionEstablished, setConnection] = useState(false);const [file, setFile] = useState();const [gotFile, setGotFile] = useState(false);const chunksRef = useRef([]);const socketRef = useRef();const peersRef = useRef([]);const peerRef = useRef();const fileNameRef = useRef("");const roomID = props.match.params.roomID;useEffect(() => {socketRef.current = io.connect("/");socketRef.current.emit("join room", roomID);socketRef.current.on("all users", users => {peerRef.current = createPeer(users[0], socketRef.current.id);});socketRef.current.on("user joined", payload => {peerRef.current = addPeer(payload.signal, payload.callerID);});socketRef.current.on("receiving returned signal", payload => {peerRef.current.signal(payload.signal);setConnection(true);});socketRef.current.on("room full", () => {alert("room is full");})}, []);function createPeer(userToSignal, callerID) {const peer = new Peer({initiator: true,trickle: false,});peer.on("signal", signal => {socketRef.current.emit("sending signal", { userToSignal, callerID, signal });});peer.on("data", handleReceivingData);return peer;}function addPeer(incomingSignal, callerID) {const peer = new Peer({initiator: false,trickle: false,});peer.on("signal", signal => {socketRef.current.emit("returning signal", { signal, callerID });});peer.on("data", handleReceivingData);peer.signal(incomingSignal);setConnection(true);return peer;}function handleReceivingData(data) {if (data.toString().includes("done")) {setGotFile(true);const parsed = JSON.parse(data);fileNameRef.current = parsed.fileName;} else {worker.postMessage(data);}}function download() {setGotFile(false);worker.postMessage("download");worker.addEventListener("message", event => {const stream = event.data.stream();const fileStream = streamSaver.createWriteStream(fileNameRef.current);stream.pipeTo(fileStream);})}function selectFile(e) {setFile(e.target.files[0]);}function sendFile() {const peer = peerRef.current;const stream = file.stream();const reader = stream.getReader();reader.read().then(obj => {handlereading(obj.done, obj.value);});function handlereading(done, value) {if (done) {peer.write(JSON.stringify({ done: true, fileName: file.name }));return;}peer.write(value);reader.read().then(obj => {handlereading(obj.done, obj.value);})}}let body;if (connectionEstablished) {body = (<div><input onChange={selectFile} type="file" /><button onClick={sendFile}>Send file</button></div>);} else {body = (<h1>Once you have a peer connection, you will be able to share files</h1>);}let downloadPrompt;if (gotFile) {downloadPrompt = (<div><span>You have received a file. Would you like to download the file?</span><button onClick={download}>Yes</button></div>);}return (<Container>{body}{downloadPrompt}</Container>);};export default Room;

let array = [];self.addEventListener("message", event => {if (event.data === "download") {const blob = new Blob(array);self.postMessage(blob);array = [];} else if (event.data === "abort") {array = [];} else {array.push(event.data);}})

-
支持几乎所有的浏览器
-
支持庞大的文档大小——正如前面提到的,这是我们为什么要实现它的基本解释。
-
一个更好的方法来破译所发送信息的度量——通过在缓冲区中发送一个记录,我们现在可以显示信息,例如,发送的文档的级别,发送记录的速度等等。
-
识别未完成发送的文件——在无法完全发送文件的情况下,现在能够以不同的方式获取和处理文件。
-
信令服务器(STUN和TURN服务器)。
-
使多个对等连接可拓展。
-
当WebRTC不能工作时才用的一种混合共享方式。
-
提高传输效率和速度。

点击【阅读原文】了解更多详细信息
文章评论