You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
3.4 KiB

  1. var WebSocketServer = require('../../').Server
  2. , express = require('express')
  3. , fs = require('fs')
  4. , http = require('http')
  5. , util = require('util')
  6. , path = require('path')
  7. , app = express.createServer()
  8. , events = require('events')
  9. , ansi = require('ansi')
  10. , cursor = ansi(process.stdout);
  11. function BandwidthSampler(ws, interval) {
  12. interval = interval || 2000;
  13. var previousByteCount = 0;
  14. var self = this;
  15. var intervalId = setInterval(function() {
  16. var byteCount = ws.bytesReceived;
  17. var bytesPerSec = (byteCount - previousByteCount) / (interval / 1000);
  18. previousByteCount = byteCount;
  19. self.emit('sample', bytesPerSec);
  20. }, interval);
  21. ws.on('close', function() {
  22. clearInterval(intervalId);
  23. });
  24. }
  25. util.inherits(BandwidthSampler, events.EventEmitter);
  26. function makePathForFile(filePath, prefix, cb) {
  27. if (typeof cb !== 'function') throw new Error('callback is required');
  28. filePath = path.dirname(path.normalize(filePath)).replace(/^(\/|\\)+/, '');
  29. var pieces = filePath.split(/(\\|\/)/);
  30. var incrementalPath = prefix;
  31. function step(error) {
  32. if (error) return cb(error);
  33. if (pieces.length == 0) return cb(null, incrementalPath);
  34. incrementalPath += '/' + pieces.shift();
  35. fs.exists(incrementalPath, function(exists) {
  36. if (!exists) fs.mkdir(incrementalPath, step);
  37. else process.nextTick(step);
  38. });
  39. }
  40. step();
  41. }
  42. cursor.eraseData(2).goto(1, 1);
  43. app.use(express.static(__dirname + '/public'));
  44. var clientId = 0;
  45. var wss = new WebSocketServer({server: app});
  46. wss.on('connection', function(ws) {
  47. var thisId = ++clientId;
  48. cursor.goto(1, 4 + thisId).eraseLine();
  49. console.log('Client #%d connected', thisId);
  50. var sampler = new BandwidthSampler(ws);
  51. sampler.on('sample', function(bps) {
  52. cursor.goto(1, 4 + thisId).eraseLine();
  53. console.log('WebSocket #%d incoming bandwidth: %d MB/s', thisId, Math.round(bps / (1024*1024)));
  54. });
  55. var filesReceived = 0;
  56. var currentFile = null;
  57. ws.on('message', function(data, flags) {
  58. if (!flags.binary) {
  59. currentFile = JSON.parse(data);
  60. // note: a real-world app would want to sanity check the data
  61. }
  62. else {
  63. if (currentFile == null) return;
  64. makePathForFile(currentFile.path, __dirname + '/uploaded', function(error, path) {
  65. if (error) {
  66. console.log(error);
  67. ws.send(JSON.stringify({event: 'error', path: currentFile.path, message: error.message}));
  68. return;
  69. }
  70. fs.writeFile(path + '/' + currentFile.name, data, function(error) {
  71. ++filesReceived;
  72. // console.log('received %d bytes long file, %s', data.length, currentFile.path);
  73. ws.send(JSON.stringify({event: 'complete', path: currentFile.path}));
  74. currentFile = null;
  75. });
  76. });
  77. }
  78. });
  79. ws.on('close', function() {
  80. cursor.goto(1, 4 + thisId).eraseLine();
  81. console.log('Client #%d disconnected. %d files received.', thisId, filesReceived);
  82. });
  83. ws.on('error', function(e) {
  84. cursor.goto(1, 4 + thisId).eraseLine();
  85. console.log('Client #%d error: %s', thisId, e.message);
  86. });
  87. });
  88. fs.mkdir(__dirname + '/uploaded', function(error) {
  89. // ignore errors, most likely means directory exists
  90. console.log('Uploaded files will be saved to %s/uploaded.', __dirname);
  91. console.log('Remember to wipe this directory if you upload lots and lots.');
  92. app.listen(8080);
  93. console.log('Listening on http://localhost:8080');
  94. });