testing file uploads w/ websockets
yarn
node server
then open index.html in yr browser
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <style> | |
| progress { display: block; } | |
| progress:empty { display: none; } | |
| </style> | |
| </head> | |
| <body> | |
| <header></header> | |
| <progress></progress> | |
| <input type="file" accept="image/jpeg"> | |
| <script> | |
| var ws = new WebSocket('ws://127.0.0.1:8899') | |
| var input = document.querySelector('input[type="file"]') | |
| var progress = document.getElementsByTagName('progress')[0] | |
| input.addEventListener('change', function (ev) { | |
| ws.send(ev.target.files[0]) | |
| }) | |
| ws.addEventListener('message', function (msg) { | |
| var data = msg.data | |
| if (typeof data === 'string') | |
| data = JSON.parse(data) | |
| if (data.type === 'greeting') { | |
| document.querySelector('header').innerHTML = '<h1>' + data.message + '</h1>' | |
| } | |
| if (data.type === 'update') { | |
| progress.max = data.total | |
| progress.value = data.current | |
| } | |
| }) | |
| </script> | |
| </body> | |
| </html> | |
| { | |
| "name": "ws-test-file-upload", | |
| "version": "0.0.0", | |
| "main": "server.js", | |
| "dependencies": { | |
| "throttle": "^1.0.3", | |
| "through2": "^2.0.3", | |
| "ws": "^1.1.1" | |
| } | |
| } |
| const WebSocket = require('ws') | |
| const fs = require('fs') | |
| const Throttle = require('throttle') | |
| const through = require('through2') | |
| const server = new WebSocket.Server({port: 8899}) | |
| let pool = 0 | |
| server.on('connection', function (ws) { | |
| pool++ | |
| ws.send(JSON.stringify({ | |
| type: 'greeting', | |
| message: 'you\'re on live w/ tha websocketz' | |
| })) | |
| console.log('connection # %d', pool) | |
| ws.on('message', function (data) { | |
| const out = fs.createWriteStream(`./image-${Date.now()}.jpg`) | |
| const rate = 1024 * 10 | |
| const total = data.length | |
| let current = 0 | |
| const thru = through(function (c, e, next) { | |
| current += c.length | |
| ws.send(JSON.stringify({type: 'update', current, total})) | |
| this.push(c) | |
| next() | |
| }) | |
| out.on('end', function () { | |
| ws.send(JSON.stringify({ | |
| type: 'status', | |
| message: 'complete', | |
| })) | |
| }) | |
| const throttle = Throttle(rate) | |
| throttle.pipe(thru).pipe(out) | |
| throttle.write(data) | |
| }) | |
| ws.on('close', function () { | |
| pool-- | |
| console.log('closed!') | |
| }) | |
| }) |
| # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | |
| # yarn lockfile v1 | |
| buffer-shims@^1.0.0: | |
| version "1.0.0" | |
| resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" | |
| core-util-is@~1.0.0: | |
| version "1.0.2" | |
| resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" | |
| debug@2: | |
| version "2.6.0" | |
| resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.0.tgz#bc596bcabe7617f11d9fa15361eded5608b8499b" | |
| dependencies: | |
| ms "0.7.2" | |
| inherits@~2.0.1: | |
| version "2.0.3" | |
| resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" | |
| isarray@~1.0.0: | |
| version "1.0.0" | |
| resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" | |
| ms@0.7.2: | |
| version "0.7.2" | |
| resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" | |
| options@>=0.0.5: | |
| version "0.0.6" | |
| resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" | |
| process-nextick-args@~1.0.6: | |
| version "1.0.7" | |
| resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" | |
| "readable-stream@>= 0.3.0", readable-stream@^2.1.5: | |
| version "2.2.2" | |
| resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" | |
| dependencies: | |
| buffer-shims "^1.0.0" | |
| core-util-is "~1.0.0" | |
| inherits "~2.0.1" | |
| isarray "~1.0.0" | |
| process-nextick-args "~1.0.6" | |
| string_decoder "~0.10.x" | |
| util-deprecate "~1.0.1" | |
| "stream-parser@>= 0.0.2": | |
| version "0.3.1" | |
| resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773" | |
| dependencies: | |
| debug "2" | |
| string_decoder@~0.10.x: | |
| version "0.10.31" | |
| resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" | |
| throttle@^1.0.3: | |
| version "1.0.3" | |
| resolved "https://registry.yarnpkg.com/throttle/-/throttle-1.0.3.tgz#8a32e4a15f1763d997948317c5ebe3ad8a41e4b7" | |
| dependencies: | |
| readable-stream ">= 0.3.0" | |
| stream-parser ">= 0.0.2" | |
| through2@^2.0.3: | |
| version "2.0.3" | |
| resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" | |
| dependencies: | |
| readable-stream "^2.1.5" | |
| xtend "~4.0.1" | |
| ultron@1.0.x: | |
| version "1.0.2" | |
| resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.0.2.tgz#ace116ab557cd197386a4e88f4685378c8b2e4fa" | |
| util-deprecate@~1.0.1: | |
| version "1.0.2" | |
| resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" | |
| ws@^1.1.1: | |
| version "1.1.1" | |
| resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.1.tgz#082ddb6c641e85d4bb451f03d52f06eabdb1f018" | |
| dependencies: | |
| options ">=0.0.5" | |
| ultron "1.0.x" | |
| xtend@~4.0.1: | |
| version "4.0.1" | |
| resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" |