mirror of https://github.com/kern/filepizza
First hacky version with socket.io instead of WebRTC.
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
|
||||
});
|
||||
|
||||
}
|
||||
@ -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…
Reference in New Issue