First hacky version with socket.io instead of WebRTC.

pull/1/head
Alex Kern 11 years ago
parent 8229c6c6dc
commit 7532673a88

@ -0,0 +1,55 @@
import DropZone from './DropZone';
import FileDescription from './FileDescription';
import React from 'react';
import Tempalink from './Tempalink';
import socket from './socket';
import upload from './upload';
import download from './download';
export default class App extends React.Component {
constructor() {
super();
this.state = { token: null, file: null };
var self = this;
socket.on('token', function (t) {
self.setState({ token: t });
});
socket.on('download', function (t) {
if (self.state.file) upload(self.state.file, t);
});
socket.on('upload', function (data) {
download(window.metadata.name, new Blob([data]));
});
if (window.token) socket.emit('download', window.token);
}
useFile(file) {
this.setState({ file: file });
socket.emit('update', {
name: file.name,
size: file.size,
type: file.type
});
}
render() {
if (this.state.file) {
return (
<div>
<FileDescription file={this.state.file} />
<Tempalink token={this.state.token} />
</div>
);
} else {
return <DropZone onDrop={this.useFile.bind(this)} />;
}
}
}

@ -0,0 +1,26 @@
import React from 'react';
export default class DropZone extends React.Component {
dragOver(e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
}
drop(e) {
e.preventDefault();
var file = e.dataTransfer.files[0];
this.props.onDrop(file);
}
render() {
return (
<div className="drop-zone"
onDragOver={this.dragOver.bind(this)}
onDrop={this.drop.bind(this)}>
Drop a file here.
</div>
);
}
}

@ -0,0 +1,15 @@
import React from 'react';
export default class FileDescription extends React.Component {
render() {
return (
<div className="file-description">
<span className="file-name">{this.props.file.name}</span>
<span className="file-size">{this.props.file.size}</span>
<span className="file-type">{this.props.file.type}</span>
</div>
);
}
}

@ -0,0 +1,12 @@
import React from 'react';
export default class Tempalink extends React.Component {
render() {
var url = window.location.origin + '/d/' + this.props.token;
return (
<a href={url} className="tempalink">{url}</a>
);
}
}

@ -0,0 +1,12 @@
export default function(name, blob) {
var reader = new FileReader();
reader.onloadend = function() {
var link = document.createElement('a');
link.download = name;
link.href = reader.result;
link.click();
};
reader.readAsDataURL(blob);
}

@ -1,74 +1,3 @@
var files = []
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
files = evt.dataTransfer.files; // FileList object.
var output = [];
metadata = [];
for (var i = 0, file; file = files[i]; i++) {
output.push('<li><strong>', escape(file.name), '</strong> (', file.type || 'n/a', ') - ',
file.size, ' bytes, last modified: ',
file.lastModifiedDate ? file.lastModifiedDate.toLocaleDateString() : 'n/a',
'</li>');
var metadaton = {"name":escape(file.name),
"size":file.size,
"type":file.type || 'n/a',
"crc" :""}
metadata.push(metadaton)
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
var firebase = new Firebase("https://webdrop.firebaseio.com/");
var id = createID()
firebase.set({
id : {
"id" : id,
"file_metadata" : metadata
}
})
}
function send() { // perhaps need params for peer id or something
for (var i = 0, file; f = files[i]; i++) {
for (var bytes = 0; bytes <= file.size; bytes += 1200) {
endingByte = bytes+1200
if (endingByte > file.size) {
endingByte = file.size
}
var blob = file.slice(bytes, endingByte);
// send blob
}
}
}
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy';
}
function createID() {
var timestamp = Date.now()
var alphabet = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", "c", "d", "e", "f", "g", "h", "i",
"j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B",
"C", "D", "E", "F", "G", "H", "I", "K", "L", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X",
"Y", "Z"]
var arr = []
var base = alphabet.length
while (timestamp > 0) {
var rem = parseInt(timestamp % base)
timestamp = parseInt(timestamp / base)
arr.push(alphabet[rem])
}
arr = arr.reverse()
id = arr.join("")
// add two random characters to ensure uniqueness between identical milliseconds
id += (alphabet[Math.floor(Math.random() * alphabet.length)])
id += (alphabet[Math.floor(Math.random() * alphabet.length)])
return id
}
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
import App from './App';
import React from 'react';
React.render(<App />, document.getElementById('app'));

@ -0,0 +1,2 @@
import io from 'socket.io-client';
export default io.connect('http://localhost:3000');

@ -0,0 +1,10 @@
import socket from './socket';
export default function (file, token) {
socket.emit('upload', {
token: token,
blob: file
});
}

@ -5,7 +5,8 @@
"main": "server/index.js",
"scripts": {
"start": "node server/index.js",
"build": "./node_modules/.bin/browserify client/index.js -o static/app.js"
"build": "./node_modules/.bin/browserify client/index.js -o static/app.js -t babelify -t reactify -d",
"watch": "./node_modules/.bin/watchify client/index.js -o static/app.js -t babelify -t reactify -d"
},
"repository": {
"type": "git",
@ -18,8 +19,17 @@
},
"homepage": "https://github.com/kern/webdrop",
"dependencies": {
"browserify": "^9.0.3",
"bases": "^0.2.1",
"ejs": "^2.3.1",
"express": "^4.12.0",
"firebase": "^2.2.1"
"socket.io": "^1.3.5"
},
"devDependencies": {
"babelify": "^5.0.4",
"browserify": "^9.0.3",
"react": "^0.13.0",
"reactify": "^1.1.0",
"socket.io-client": "^1.3.5",
"watchify": "^2.4.0"
}
}

@ -0,0 +1,42 @@
var bases = require('bases');
var crypto = require('crypto');
var tokenLength = 8;
var tokens = {};
var Client = module.exports = function (socket) {
var maxNum = Math.pow(62, tokenLength);
var numBytes = Math.ceil(Math.log(maxNum) / Math.log(256));
var token = '';
do {
do {
var bytes = crypto.randomBytes(numBytes);
var num = 0
for (var i = 0; i < bytes.length; i++) {
num += Math.pow(256, i) * bytes[i];
}
} while (num >= maxNum);
token = bases.toBase62(num);
} while (token in tokens);
this.token = token;
this.socket = socket;
tokens[this.token] = this;
};
Client.exists = function (token) {
return token in tokens;
};
Client.find = function (token) {
return tokens[token];
};
Client.remove = function (client) {
delete tokens[client.token];
};

@ -1,15 +0,0 @@
var express = require('express');
var path = require('path');
var app = module.exports = express();
var db = require('./db');
var greeting = 'Hello World!';
db.child('greeting').on('value', function(snapshot) {
greeting = snapshot.val();
});
app.get('/', function (req, res) {
res.sendFile(path.resolve(__dirname + '/../static/index.html'));
});
app.use(express.static(__dirname + '/../static'));

@ -1,2 +0,0 @@
var Firebase = require('firebase');
var db = module.exports = new Firebase('https://webdrop.firebaseio.com/');

@ -1,7 +1,65 @@
var app = require('./app');
var Client = require('./Client');
var express = require('express');
var http = require('http');
var path = require('path');
var socketIO = require('socket.io');
var server = app.listen(process.env.PORT || 3000, function () {
var app = express();
var server = http.Server(app);
var io = socketIO(server);
server.listen(process.env.PORT || 3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('WebDrop listening on %s:%s', host, port);
})
});
app.set('view engine', 'ejs');
app.set('views', path.resolve(__dirname, '../views'));
app.get('/', function (req, res) {
res.render('index');
});
app.get('/d/:token', function (req, res) {
console.log("Downloading from:", req.params.token);
var uploader = Client.find(req.params.token);
res.render('download', {
token: uploader.token,
meta: uploader.metadata
});
});
app.use(express.static(__dirname + '/../static'));
io.on('connection', function (socket) {
var client = new Client(socket);
socket.emit('token', client.token);
function log(type, data) {
console.log(client.token, '.', type, ':', data);
}
socket.on('upload', function (data) {
var downloader = Client.find(data.token);
downloader.socket.emit('upload', data.blob);
log('upload', data);
});
socket.on('download', function (token) {
var uploader = Client.find(token);
uploader.socket.emit('download', client.token);
log('download', token);
});
socket.on('update', function (data) {
client.metadata = data;
log('update', data);
});
socket.on('disconnect', function () {
Client.remove(client);
});
});

File diff suppressed because one or more lines are too long

@ -1,11 +0,0 @@
<head>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="drop_zone">Drop Files Here</div>
<output id="list"></output>
</body>
<script src="https://cdn.firebase.com/js/client/2.2.1/firebase.js"></script>
<script src="app.js"></script>

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>webdrop</title>
<link rel="stylesheet" href="/index.css">
<script src="/socket.io/socket.io.js"></script>
<script src="https://cdn.firebase.com/js/client/2.2.1/firebase.js"></script>
</head>
<body>
<script>
window.token = <%- JSON.stringify(token) %>;
window.metadata = <%- JSON.stringify(meta) %>;
</script>
<div id="app"></div>
<script src="/app.js"></script>
</body>
</html>

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>webdrop</title>
<link rel="stylesheet" href="index.css">
<script src="/socket.io/socket.io.js"></script>
<script src="https://cdn.firebase.com/js/client/2.2.1/firebase.js"></script>
</head>
<body>
<div id="app"></div>
<script src="/app.js"></script>
</body>
</html>
Loading…
Cancel
Save