SkyRTC-client.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. const SkyRTC = function () {
  2. //创建本地流
  3. let gThat;
  4. let PeerConnection = (window.PeerConnection || window.webkitPeerConnection00 || window.webkitRTCPeerConnection ||
  5. window.mozRTCPeerConnection);
  6. let getUserMedia = (navigator.getUserMedia ||//旧版API
  7. navigator.mediaDevices.getUserMedia ||//最新的标准API
  8. navigator.webkitGetUserMedia || //webkit核心浏览器
  9. navigator.mozGetUserMedia || //firfox浏览器
  10. navigator.msGetUserMedia
  11. );
  12. let nativeRTCIceCandidate = (window.mozRTCIceCandidate || window.RTCIceCandidate);
  13. let nativeRTCSessionDescription = (window.mozRTCSessionDescription || window.RTCSessionDescription);
  14. const iceServer = {
  15. "iceServers": [
  16. {
  17. "url":"stun:118.178.91.140:3478"
  18. },
  19. {
  20. "url": "turn:118.178.91.140:3478",
  21. "username": "iturn",
  22. "credential": "Inspu9961234,"
  23. }
  24. ]
  25. };
  26. let packetSize = 1000;
  27. /* 事件处理器 */
  28. function EventEmitter() {
  29. this.events = {};
  30. }
  31. //绑定事件函数
  32. EventEmitter.prototype.on = function (eventName, callback) {
  33. this.events[eventName] = this.events[eventName] || [];
  34. this.events[eventName].push(callback);
  35. };
  36. //触发事件函数
  37. EventEmitter.prototype.emit = function (eventName, _) {
  38. var events = this.events[eventName],
  39. args = Array.prototype.slice.call(arguments, 1),
  40. i, m;
  41. if (!events) {
  42. return;
  43. }
  44. for (i = 0, m = events.length; i < m; i++) {
  45. events[i].apply(null, args);
  46. }
  47. };
  48. /**********************************************************/
  49. /* 流及信道建立部分 */
  50. /**********************************************************/
  51. /*******************基础部分*********************/
  52. function skyrtc() {
  53. //本地media stream
  54. this.localMediaStream = null;
  55. //所在房间
  56. this.room = "";
  57. //接收文件时用于暂存接收文件
  58. this.fileData = {};
  59. //本地WebSocket连接
  60. this.socket = null;
  61. //本地socket的id,由后台服务器创建
  62. this.me = null;
  63. //保存所有与本地相连的peer connection, 键为socket id,值为PeerConnection类型
  64. this.peerConnections = {};
  65. //保存所有与本地连接的socket的id
  66. this.connections = [];
  67. //初始时需要构建链接的数目
  68. this.numStreams = 0;
  69. //初始时已经连接的数目
  70. this.initializedStreams = 0;
  71. //保存所有的data channel,键为socket id,值通过PeerConnection实例的createChannel创建
  72. this.dataChannels = {};
  73. //保存所有发文件的data channel及其发文件状态
  74. this.fileChannels = {};
  75. //保存所有接受到的文件
  76. this.receiveFiles = {};
  77. }
  78. //继承自事件处理器,提供绑定事件和触发事件的功能
  79. skyrtc.prototype = new EventEmitter();
  80. /*************************服务器连接部分***************************/
  81. skyrtc.prototype.connect = function (server, room) {
  82. var socket,
  83. that = this;
  84. room = room || "";
  85. socket = this.socket = new WebSocket(server);
  86. socket.onopen = function () {
  87. socket.send(JSON.stringify({
  88. "eventName": "__join",
  89. "data": {
  90. "room": room
  91. }
  92. }));
  93. that.emit("socket_opened", socket);
  94. };
  95. socket.onmessage = function (message) {
  96. var json = JSON.parse(message.data);
  97. if (json.eventName) {
  98. that.emit(json.eventName, json.data);
  99. } else {
  100. that.emit("socket_receive_message", socket, json);
  101. }
  102. };
  103. socket.onerror = function (error) {
  104. that.emit("socket_error", error, socket);
  105. };
  106. socket.onclose = function (data) {
  107. that.localMediaStream.close();
  108. var pcs = that.peerConnections;
  109. for (i = pcs.length; i--;) {
  110. that.closePeerConnection(pcs[i]);
  111. }
  112. that.peerConnections = [];
  113. that.dataChannels = {};
  114. that.fileChannels = {};
  115. that.connections = [];
  116. that.fileData = {};
  117. that.emit('socket_closed', socket);
  118. };
  119. this.on('_peers', function (data) {
  120. //获取所有服务器上的
  121. that.connections = data.connections;
  122. that.me = data.you;
  123. that.emit("get_peers", that.connections);
  124. that.emit('connected', socket);
  125. });
  126. this.on("_ice_candidate", function (data) {
  127. var candidate = new nativeRTCIceCandidate(data);
  128. var pc = that.peerConnections[data.socketId];
  129. if (!pc || !pc.remoteDescription.type) {
  130. //push candidate onto queue...
  131. console.log("remote not set!")
  132. }
  133. pc.addIceCandidate(candidate);
  134. that.emit('get_ice_candidate', candidate);
  135. });
  136. this.on('_new_peer', function (data) {
  137. that.connections.push(data.socketId);
  138. var pc = that.createPeerConnection(data.socketId),
  139. i, m;
  140. pc.addStream(that.localMediaStream);
  141. that.emit('new_peer', data.socketId);
  142. });
  143. this.on('_remove_peer', function (data) {
  144. var sendId;
  145. that.closePeerConnection(that.peerConnections[data.socketId]);
  146. delete that.peerConnections[data.socketId];
  147. delete that.dataChannels[data.socketId];
  148. for (sendId in that.fileChannels[data.socketId]) {
  149. that.emit("send_file_error", new Error("Connection has been closed"), data.socketId, sendId, that.fileChannels[
  150. data.socketId][sendId].file);
  151. }
  152. delete that.fileChannels[data.socketId];
  153. that.emit("remove_peer", data.socketId);
  154. });
  155. this.on('_offer', function (data) {
  156. that.receiveOffer(data.socketId, data.sdp);
  157. that.emit("get_offer", data);
  158. });
  159. this.on('_answer', function (data) {
  160. that.receiveAnswer(data.socketId, data.sdp);
  161. that.emit('get_answer', data);
  162. });
  163. this.on('send_file_error', function (error, socketId, sendId, file) {
  164. that.cleanSendFile(sendId, socketId);
  165. });
  166. this.on('receive_file_error', function (error, sendId) {
  167. that.cleanReceiveFile(sendId);
  168. });
  169. this.on('ready', function () {
  170. that.createPeerConnections();
  171. that.addStreams();
  172. that.addDataChannels();
  173. that.sendOffers();
  174. });
  175. };
  176. /*************************流处理部分*******************************/
  177. //访问用户媒体设备的兼容方法
  178. function getUserMediaFun(constraints, success, error) {
  179. if (navigator.mediaDevices.getUserMedia) {
  180. //最新的标准API
  181. navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
  182. } else if (navigator.webkitGetUserMedia) {
  183. //webkit核心浏览器
  184. navigator.webkitGetUserMedia(constraints, success, error)
  185. } else if (navigator.mozGetUserMedia) {
  186. //firfox浏览器
  187. navigator.mozGetUserMedia(constraints, success, error);
  188. } else if (navigator.getUserMedia) {
  189. //旧版API
  190. navigator.getUserMedia(constraints, success, error);
  191. } else {
  192. that.emit("stream_create_error", new Error('WebRTC is not yet supported in this browser.'));
  193. }
  194. }
  195. function createStreamSuccess(stream) {
  196. if (gThat) {
  197. gThat.localMediaStream = stream;
  198. gThat.initializedStreams++;
  199. gThat.emit("stream_created", stream);
  200. if (gThat.initializedStreams === gThat.numStreams) {
  201. gThat.emit("ready");
  202. }
  203. }
  204. }
  205. function createStreamError(error) {
  206. if (gThat) {
  207. gThat.emit("stream_create_error", error);
  208. }
  209. }
  210. skyrtc.prototype.createStream = function (options) {
  211. var that = this;
  212. gThat = this;
  213. options.video = !!options.video;
  214. options.audio = !!options.audio;
  215. if (getUserMedia) {
  216. this.numStreams++;
  217. // 调用用户媒体设备, 访问摄像头
  218. getUserMediaFun(options, createStreamSuccess, createStreamError);
  219. } else {
  220. that.emit("stream_create_error", new Error('WebRTC is not yet supported in this browser.'));
  221. }
  222. };
  223. //将本地流添加到所有的PeerConnection实例中
  224. skyrtc.prototype.addStreams = function () {
  225. var i, m,
  226. stream,
  227. connection;
  228. for (connection in this.peerConnections) {
  229. this.peerConnections[connection].addStream(this.localMediaStream);
  230. }
  231. };
  232. // 将流绑定到video标签上用于输出
  233. skyrtc.prototype.attachStream = function (stream, domId) {
  234. var element = document.getElementById(domId);
  235. if (navigator.mediaDevices.getUserMedia) {
  236. element.srcObject = stream;
  237. } else {
  238. element.src = webkitURL.createObjectURL(stream);
  239. }
  240. element.play();
  241. };
  242. /***********************信令交换部分*******************************/
  243. //向所有PeerConnection发送Offer类型信令
  244. skyrtc.prototype.sendOffers = function () {
  245. var i, m,
  246. pc,
  247. that = this,
  248. pcCreateOfferCbGen = function (pc, socketId) {
  249. return function (session_desc) {
  250. pc.setLocalDescription(session_desc);
  251. that.socket.send(JSON.stringify({
  252. "eventName": "__offer",
  253. "data": {
  254. "sdp": session_desc,
  255. "socketId": socketId
  256. }
  257. }));
  258. };
  259. },
  260. pcCreateOfferErrorCb = function (error) {
  261. console.log(error);
  262. };
  263. for (i = 0, m = this.connections.length; i < m; i++) {
  264. pc = this.peerConnections[this.connections[i]];
  265. pc.createOffer(pcCreateOfferCbGen(pc, this.connections[i]), pcCreateOfferErrorCb);
  266. }
  267. };
  268. //接收到Offer类型信令后作为回应返回answer类型信令
  269. skyrtc.prototype.receiveOffer = function (socketId, sdp) {
  270. var pc = this.peerConnections[socketId];
  271. this.sendAnswer(socketId, sdp);
  272. };
  273. //发送answer类型信令
  274. skyrtc.prototype.sendAnswer = function (socketId, sdp) {
  275. var pc = this.peerConnections[socketId];
  276. var that = this;
  277. pc.setRemoteDescription(new nativeRTCSessionDescription(sdp));
  278. pc.createAnswer(function (session_desc) {
  279. pc.setLocalDescription(session_desc);
  280. that.socket.send(JSON.stringify({
  281. "eventName": "__answer",
  282. "data": {
  283. "socketId": socketId,
  284. "sdp": session_desc
  285. }
  286. }));
  287. }, function (error) {
  288. console.log(error);
  289. });
  290. };
  291. //接收到answer类型信令后将对方的session描述写入PeerConnection中
  292. skyrtc.prototype.receiveAnswer = function (socketId, sdp) {
  293. var pc = this.peerConnections[socketId];
  294. pc.setRemoteDescription(new nativeRTCSessionDescription(sdp));
  295. };
  296. /***********************点对点连接部分*****************************/
  297. //创建与其他用户连接的PeerConnections
  298. skyrtc.prototype.createPeerConnections = function () {
  299. var i, m;
  300. for (i = 0, m = this.connections.length; i < m; i++) {
  301. this.createPeerConnection(this.connections[i]);
  302. }
  303. };
  304. //创建单个PeerConnection
  305. skyrtc.prototype.createPeerConnection = function (socketId) {
  306. var that = this;
  307. var pc = new PeerConnection(iceServer);
  308. this.peerConnections[socketId] = pc;
  309. pc.onicecandidate = function (evt) {
  310. if (evt.candidate)
  311. that.socket.send(JSON.stringify({
  312. "eventName": "__ice_candidate",
  313. "data": {
  314. "id": evt.candidate.sdpMid,
  315. "label": evt.candidate.sdpMLineIndex,
  316. "sdpMLineIndex": evt.candidate.sdpMLineIndex,
  317. "candidate": evt.candidate.candidate,
  318. "socketId": socketId
  319. }
  320. }));
  321. that.emit("pc_get_ice_candidate", evt.candidate, socketId, pc);
  322. };
  323. pc.onopen = function () {
  324. that.emit("pc_opened", socketId, pc);
  325. };
  326. pc.onaddstream = function (evt) {
  327. that.emit('pc_add_stream', evt.stream, socketId, pc);
  328. };
  329. pc.ondatachannel = function (evt) {
  330. that.addDataChannel(socketId, evt.channel);
  331. that.emit('pc_add_data_channel', evt.channel, socketId, pc);
  332. };
  333. return pc;
  334. };
  335. //关闭PeerConnection连接
  336. skyrtc.prototype.closePeerConnection = function (pc) {
  337. if (!pc) return;
  338. pc.close();
  339. };
  340. /***********************数据通道连接部分*****************************/
  341. //消息广播
  342. skyrtc.prototype.broadcast = function (message) {
  343. var socketId;
  344. for (socketId in this.dataChannels) {
  345. this.sendMessage(message, socketId);
  346. }
  347. };
  348. //发送消息方法
  349. skyrtc.prototype.sendMessage = function (message, socketId) {
  350. if (this.dataChannels[socketId].readyState.toLowerCase() === 'open') {
  351. this.dataChannels[socketId].send(JSON.stringify({
  352. type: "__msg",
  353. data: message
  354. }));
  355. }
  356. };
  357. //对所有的PeerConnections创建Data channel
  358. skyrtc.prototype.addDataChannels = function () {
  359. var connection;
  360. for (connection in this.peerConnections) {
  361. this.createDataChannel(connection);
  362. }
  363. };
  364. //对某一个PeerConnection创建Data channel
  365. skyrtc.prototype.createDataChannel = function (socketId, label) {
  366. var pc, key, channel;
  367. pc = this.peerConnections[socketId];
  368. if (!socketId) {
  369. this.emit("data_channel_create_error", socketId, new Error("attempt to create data channel without socket id"));
  370. }
  371. if (!(pc instanceof PeerConnection)) {
  372. this.emit("data_channel_create_error", socketId, new Error("attempt to create data channel without peerConnection"));
  373. }
  374. try {
  375. channel = pc.createDataChannel(label);
  376. } catch (error) {
  377. this.emit("data_channel_create_error", socketId, error);
  378. }
  379. return this.addDataChannel(socketId, channel);
  380. };
  381. //为Data channel绑定相应的事件回调函数
  382. skyrtc.prototype.addDataChannel = function (socketId, channel) {
  383. var that = this;
  384. channel.onopen = function () {
  385. that.emit('data_channel_opened', channel, socketId);
  386. };
  387. channel.onclose = function (event) {
  388. delete that.dataChannels[socketId];
  389. that.emit('data_channel_closed', channel, socketId);
  390. };
  391. channel.onmessage = function (message) {
  392. var json;
  393. json = JSON.parse(message.data);
  394. if (json.type === '__file') {
  395. /*that.receiveFileChunk(json);*/
  396. that.parseFilePacket(json, socketId);
  397. } else {
  398. that.emit('data_channel_message', channel, socketId, json.data);
  399. }
  400. };
  401. channel.onerror = function (err) {
  402. that.emit('data_channel_error', channel, socketId, err);
  403. };
  404. this.dataChannels[socketId] = channel;
  405. return channel;
  406. };
  407. /**********************************************************/
  408. /* */
  409. /* 文件传输 */
  410. /* */
  411. /**********************************************************/
  412. /************************公有部分************************/
  413. //解析Data channel上的文件类型包,来确定信令类型
  414. skyrtc.prototype.parseFilePacket = function (json, socketId) {
  415. var signal = json.signal,
  416. that = this;
  417. if (signal === 'ask') {
  418. that.receiveFileAsk(json.sendId, json.name, json.size, socketId);
  419. } else if (signal === 'accept') {
  420. that.receiveFileAccept(json.sendId, socketId);
  421. } else if (signal === 'refuse') {
  422. that.receiveFileRefuse(json.sendId, socketId);
  423. } else if (signal === 'chunk') {
  424. that.receiveFileChunk(json.data, json.sendId, socketId, json.last, json.percent);
  425. } else if (signal === 'close') {
  426. //TODO
  427. }
  428. };
  429. /***********************发送者部分***********************/
  430. //通过Dtata channel向房间内所有其他用户广播文件
  431. skyrtc.prototype.shareFile = function (dom) {
  432. var socketId,
  433. that = this;
  434. for (socketId in that.dataChannels) {
  435. that.sendFile(dom, socketId);
  436. }
  437. };
  438. //向某一单个用户发送文件
  439. skyrtc.prototype.sendFile = function (dom, socketId) {
  440. var that = this,
  441. file,
  442. reader,
  443. fileToSend,
  444. sendId;
  445. if (typeof dom === 'string') {
  446. dom = document.getElementById(dom);
  447. }
  448. if (!dom) {
  449. that.emit("send_file_error", new Error("Can not find dom while sending file"), socketId);
  450. return;
  451. }
  452. if (!dom.files || !dom.files[0]) {
  453. that.emit("send_file_error", new Error("No file need to be sended"), socketId);
  454. return;
  455. }
  456. file = dom.files[0];
  457. that.fileChannels[socketId] = that.fileChannels[socketId] || {};
  458. sendId = that.getRandomString();
  459. fileToSend = {
  460. file: file,
  461. state: "ask"
  462. };
  463. that.fileChannels[socketId][sendId] = fileToSend;
  464. that.sendAsk(socketId, sendId, fileToSend);
  465. that.emit("send_file", sendId, socketId, file);
  466. };
  467. //发送多个文件的碎片
  468. skyrtc.prototype.sendFileChunks = function () {
  469. var socketId,
  470. sendId,
  471. that = this,
  472. nextTick = false;
  473. for (socketId in that.fileChannels) {
  474. for (sendId in that.fileChannels[socketId]) {
  475. if (that.fileChannels[socketId][sendId].state === "send") {
  476. nextTick = true;
  477. that.sendFileChunk(socketId, sendId);
  478. }
  479. }
  480. }
  481. if (nextTick) {
  482. setTimeout(function () {
  483. that.sendFileChunks();
  484. }, 10);
  485. }
  486. };
  487. //发送某个文件的碎片
  488. skyrtc.prototype.sendFileChunk = function (socketId, sendId) {
  489. var that = this,
  490. fileToSend = that.fileChannels[socketId][sendId],
  491. packet = {
  492. type: "__file",
  493. signal: "chunk",
  494. sendId: sendId
  495. },
  496. channel;
  497. fileToSend.sendedPackets++;
  498. fileToSend.packetsToSend--;
  499. if (fileToSend.fileData.length > packetSize) {
  500. packet.last = false;
  501. packet.data = fileToSend.fileData.slice(0, packetSize);
  502. packet.percent = fileToSend.sendedPackets / fileToSend.allPackets * 100;
  503. that.emit("send_file_chunk", sendId, socketId, fileToSend.sendedPackets / fileToSend.allPackets * 100, fileToSend.file);
  504. } else {
  505. packet.data = fileToSend.fileData;
  506. packet.last = true;
  507. fileToSend.state = "end";
  508. that.emit("sended_file", sendId, socketId, fileToSend.file);
  509. that.cleanSendFile(sendId, socketId);
  510. }
  511. channel = that.dataChannels[socketId];
  512. if (!channel) {
  513. that.emit("send_file_error", new Error("Channel has been destoried"), socketId, sendId, fileToSend.file);
  514. return;
  515. }
  516. channel.send(JSON.stringify(packet));
  517. fileToSend.fileData = fileToSend.fileData.slice(packet.data.length);
  518. };
  519. //发送文件请求后若对方同意接受,开始传输
  520. skyrtc.prototype.receiveFileAccept = function (sendId, socketId) {
  521. var that = this,
  522. fileToSend,
  523. reader,
  524. initSending = function (event, text) {
  525. fileToSend.state = "send";
  526. fileToSend.fileData = event.target.result;
  527. fileToSend.sendedPackets = 0;
  528. fileToSend.packetsToSend = fileToSend.allPackets = parseInt(fileToSend.fileData.length / packetSize, 10);
  529. that.sendFileChunks();
  530. };
  531. fileToSend = that.fileChannels[socketId][sendId];
  532. reader = new window.FileReader(fileToSend.file);
  533. reader.readAsDataURL(fileToSend.file);
  534. reader.onload = initSending;
  535. that.emit("send_file_accepted", sendId, socketId, that.fileChannels[socketId][sendId].file);
  536. };
  537. //发送文件请求后若对方拒绝接受,清除掉本地的文件信息
  538. skyrtc.prototype.receiveFileRefuse = function (sendId, socketId) {
  539. var that = this;
  540. that.fileChannels[socketId][sendId].state = "refused";
  541. that.emit("send_file_refused", sendId, socketId, that.fileChannels[socketId][sendId].file);
  542. that.cleanSendFile(sendId, socketId);
  543. };
  544. //清除发送文件缓存
  545. skyrtc.prototype.cleanSendFile = function (sendId, socketId) {
  546. var that = this;
  547. delete that.fileChannels[socketId][sendId];
  548. };
  549. //发送文件请求
  550. skyrtc.prototype.sendAsk = function (socketId, sendId, fileToSend) {
  551. var that = this,
  552. channel = that.dataChannels[socketId],
  553. packet;
  554. if (!channel) {
  555. that.emit("send_file_error", new Error("Channel has been closed"), socketId, sendId, fileToSend.file);
  556. }
  557. packet = {
  558. name: fileToSend.file.name,
  559. size: fileToSend.file.size,
  560. sendId: sendId,
  561. type: "__file",
  562. signal: "ask"
  563. };
  564. channel.send(JSON.stringify(packet));
  565. };
  566. //获得随机字符串来生成文件发送ID
  567. skyrtc.prototype.getRandomString = function () {
  568. return (Math.random() * new Date().getTime()).toString(36).toUpperCase().replace(/\./g, '-');
  569. };
  570. /***********************接收者部分***********************/
  571. //接收到文件碎片
  572. skyrtc.prototype.receiveFileChunk = function (data, sendId, socketId, last, percent) {
  573. var that = this,
  574. fileInfo = that.receiveFiles[sendId];
  575. if (!fileInfo.data) {
  576. fileInfo.state = "receive";
  577. fileInfo.data = "";
  578. }
  579. fileInfo.data = fileInfo.data || "";
  580. fileInfo.data += data;
  581. if (last) {
  582. fileInfo.state = "end";
  583. that.getTransferedFile(sendId);
  584. } else {
  585. that.emit("receive_file_chunk", sendId, socketId, fileInfo.name, percent);
  586. }
  587. };
  588. //接收到所有文件碎片后将其组合成一个完整的文件并自动下载
  589. skyrtc.prototype.getTransferedFile = function (sendId) {
  590. var that = this,
  591. fileInfo = that.receiveFiles[sendId],
  592. hyperlink = document.createElement("a"),
  593. mouseEvent = new MouseEvent('click', {
  594. view: window,
  595. bubbles: true,
  596. cancelable: true
  597. });
  598. hyperlink.href = fileInfo.data;
  599. hyperlink.target = '_blank';
  600. hyperlink.download = fileInfo.name || dataURL;
  601. hyperlink.dispatchEvent(mouseEvent);
  602. (window.URL || window.webkitURL).revokeObjectURL(hyperlink.href);
  603. that.emit("receive_file", sendId, fileInfo.socketId, fileInfo.name);
  604. that.cleanReceiveFile(sendId);
  605. };
  606. //接收到发送文件请求后记录文件信息
  607. skyrtc.prototype.receiveFileAsk = function (sendId, fileName, fileSize, socketId) {
  608. var that = this;
  609. that.receiveFiles[sendId] = {
  610. socketId: socketId,
  611. state: "ask",
  612. name: fileName,
  613. size: fileSize
  614. };
  615. that.emit("receive_file_ask", sendId, socketId, fileName, fileSize);
  616. };
  617. //发送同意接收文件信令
  618. skyrtc.prototype.sendFileAccept = function (sendId) {
  619. var that = this,
  620. fileInfo = that.receiveFiles[sendId],
  621. channel = that.dataChannels[fileInfo.socketId],
  622. packet;
  623. if (!channel) {
  624. that.emit("receive_file_error", new Error("Channel has been destoried"), sendId, socketId);
  625. }
  626. packet = {
  627. type: "__file",
  628. signal: "accept",
  629. sendId: sendId
  630. };
  631. channel.send(JSON.stringify(packet));
  632. };
  633. //发送拒绝接受文件信令
  634. skyrtc.prototype.sendFileRefuse = function (sendId) {
  635. var that = this,
  636. fileInfo = that.receiveFiles[sendId],
  637. channel = that.dataChannels[fileInfo.socketId],
  638. packet;
  639. if (!channel) {
  640. that.emit("receive_file_error", new Error("Channel has been destoried"), sendId, socketId);
  641. }
  642. packet = {
  643. type: "__file",
  644. signal: "refuse",
  645. sendId: sendId
  646. };
  647. channel.send(JSON.stringify(packet));
  648. that.cleanReceiveFile(sendId);
  649. };
  650. //清除接受文件缓存
  651. skyrtc.prototype.cleanReceiveFile = function (sendId) {
  652. var that = this;
  653. delete that.receiveFiles[sendId];
  654. };
  655. return new skyrtc();
  656. };