Skip to content
This repository has been archived by the owner on Nov 28, 2023. It is now read-only.

Commit

Permalink
Release v2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Einaudi committed Dec 13, 2016
2 parents 76814aa + af1a720 commit d23b3b9
Show file tree
Hide file tree
Showing 36 changed files with 76,783 additions and 411 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
language: node_js
node_js:
- "0.11"

51 changes: 40 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,61 @@
# Just Drop It
[![Build Status](https://travis-ci.org/Orange-OpenSource/just-drop-it.svg?branch=master)](https://travis-ci.org/Orange-OpenSource/just-drop-it)

just-drop-it allows you to simply and instantly send a file to a friend, whatever your network configuration (proxies, VPN, and such). Just open your browser, drop the file in it and send the generated link to your friend : the file will be beamed to him without being stored on any platform.

## Goal
Working in companies, we have been confronted with proxies and tool that are hard to use.
The aim of the _just drop it_ is to allow its users to transfert files through the network by using **http** and **websocket** protocols.
### why would anyone do this?
We thought that this kind of tool was missing in our work environment, so we tried to set one up. Lucky for us, tools like [node.js](https://nodejs.org/), [Express](http://expressjs.com/), [socket.IO](http://socket.io/) and [socket.IO-stream](https://github.com/nkzawa/socket.io-stream) made it quite easy to get something up and running.

## Design
All the sender has to do is to navigate to the site where _just drop it_ is deployed, give a file using the form, and then a link will be given. He only has to give the link to any receivers he wants, **provided that** he does not close its window. The link will remain active as long as he lets his window opened.
## How to use it
It couldn't be more simple (but you will need a running instance of just-drop-it. If you don't have one see [the section below](##how-to-run-it) or wait for our online demo (*if a few days, we promise* :grin:)

## Framework
- open your just-drop-it in your browser
- drop your file (*just one please*)

![Image of Yaktocat](http://orange-opensource.github.io/just-drop-it/drop.png)

- send the generated link to your friends

![Image of Yaktocat](http://orange-opensource.github.io/just-drop-it/link.png)

- **keep your browser open** until your friends received the complete file

![Image of Yaktocat](http://orange-opensource.github.io/just-drop-it/transfer.png)

## How to run it

### on any computer
You will need both [npm](https://www.npmjs.com/) and [node.js](https://nodejs.org/) if you want to run it.

* Download the source code
* run `npm install` to download the needed dependencies
* `node server.js` will start node-js server

### on an openshift instance
just-drop-it should work on [openshift] (http://openshift.redhat.com/) instances. Juste create a node-js 0.10 app and synchronize its git repository with our.

## From a technical point of view
More details on our implementation, to be updated.

### Framework
To meet the requirements, we chose the followings:

- [Node Js](https://nodejs.org/)
- [Express](http://expressjs.com/)
- [socket.io](http://socket.io/): this allows us communication between clients and server.
- [socket.io stream](https://github.com/nkzawa/socket.io-stream): this allows us to stream the file between sender and server.

## Error handling
### Error handling
Handling network cutting is a hassle. The most common scenario is the following:

- a big file transfert is ongoing
- one of the proxies cut the transfert connection
- Not only neither the server nor the receiver are notified that the transfert failed, but also will the download in browser be let in a *success* state, even if all the file size was not received.
- a big file transfer is ongoing
- one of the proxies cut the transfer connection
- Not only neither the server nor the receiver are notified that the transfer failed, but also will the download in browser be let in a *success* state, even if all the file size was not received.

In order to provide a better monitoring, the number of bytes written on the http download socket are monitored, allowing us to:

- provide real download progress
- close a transfert that has been closed by the network
- close a transfer that has been closed by the network
- control that when a socket is closed, all the file size bytes has been written on it


Expand Down
9 changes: 7 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ var javascript = require('./routes/javascript');

var app = express();

global.DROP_IT_VERSION=2.1;
global.DROP_IT_VERSION=2.2;

// view engine setup
app.set('views', path.join(__dirname, 'views'));
Expand All @@ -43,6 +43,7 @@ app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, path.join('node_modules', 'tether', 'dist'))));
app.use(express.static(path.join(__dirname, path.join('node_modules', 'boosted', 'dist'))));
app.use(express.static(path.join(__dirname, path.join('node_modules', 'jquery', 'dist','cdn'))));
app.use(express.static(path.join(__dirname, path.join('node_modules', 'jquery-file-download', 'src','Scripts'))));
Expand All @@ -60,6 +61,7 @@ app.use(function(req, res, next) {
console.log("not found");
var err = new Error('Not Found');
err.status = 404;
err.sub_message = "";
next(err);
});

Expand All @@ -75,6 +77,7 @@ if (app.get('env') === 'development') {
res.render('error', {
jdropitVersion: global.DROP_IT_VERSION,
message: err.message,
sub_message: err.sub_message,
error: err
});
});
Expand All @@ -87,8 +90,10 @@ if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
isLocal : typeof process.env.OPENSHIFT_NODEJS_IP === "undefined",
message: err.message,
error: {}
sub_message: err.sub_message,
stack: err.stack
});
});

Expand Down
8 changes: 4 additions & 4 deletions client/jdropit-receive.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ function ReceiverHandler(isLocal, senderId, fileName, fileSize) {
this.filename = fileName,
this.filesize = fileSize,
this.socket = null,
this.progressBar = $("#transferProgressBar"),
this.progressBar = $("#progress"),
this.displayProgressBar = $("#progress-display"),
this.totalTries = 0,
this._init(isLocal, senderId);
//TODO debug filename
Expand All @@ -40,9 +41,8 @@ function ReceiverHandler(isLocal, senderId, fileName, fileSize) {

ReceiverHandler.prototype.displayProgress = function (percent) {
debug("displayProgress=%d", percent);
this.progressBar.attr('aria-valuenow', percent);
this.progressBar.width(percent + '%');
this.progressBar.html(percent + '%');
this.progressBar.attr('value', percent);
this.displayProgressBar.html(percent + '%');
};

ReceiverHandler.prototype.downloadComplete = function () {
Expand Down
67 changes: 38 additions & 29 deletions client/jdropit-send.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ SenderHandler.prototype = {
$.each(that.receiverInfos, function (receiverId, receiverInfo) {
if (receiverInfo.active) {
debug("Receiver id %s failed", receiverId);
that.transfertEnded(receiverId, true, "your friend did not received the file", "File not sent");
that.transfertEnded(receiverId, true, "your friend did not received the file");
} else {
debug("Receiver id %s not active", receiverId);
}
Expand All @@ -77,14 +77,15 @@ SenderHandler.prototype = {
this.socket.on('server_rcv_url_generated', function (url) {
debug("url generated - %s", url);
that.receiverUrl = window.location.host + url;
$('#generatedurl').html("<p>http://" + that.receiverUrl + " </p> ");
$('#generatedurlreminder').html("&nbsp;(http://" + that.receiverUrl + ")");
$('#generatedurl').html("http://" + that.receiverUrl);
$('#generatedurlreminder').html("http://" + that.receiverUrl);

});


this.socket.on('server_receiver_ready', function (receiverId) {
$('#copyLinkContainer').hide();
$('#transfertMessage').html("Transfert in progress...");
$('#transfertMessage').html("Transfer in progress...");

//init container
var transferContainer = $('#transferContainer');
Expand All @@ -94,32 +95,28 @@ SenderHandler.prototype = {
var newRow = rowReceiverTemplate.clone();
newRow.removeAttr("id");
newRow.show();
var linkContainer = newRow.children(".col-xs-1");
var linkRemove = linkContainer.children("a");
var linkRemove = newRow.find(".icon-delete");
linkRemove.on("click", function (e) {
e.preventDefault();
newRow.hide();
});
linkRemove.tooltip();

var pbContainer = newRow.children(".col-xs-9");
var transferProgressBar = pbContainer.find(".progress-bar");

var pbContainer = newRow.children(".col-xs-7");
var transferProgressBar = pbContainer.find("progress");
var displayProgressBar = pbContainer.find(".text-xs-center");
displayProgressBar.attr("id", "progress-"+receiverId);
transferProgressBar.attr("aria-describedby", "progress-"+receiverId);
transferContainer.append(newRow);
that.receiverInfos[receiverId] = new ReceiverInfo(pbContainer, transferProgressBar, linkContainer);
that.receiverInfos[receiverId] = new ReceiverInfo(pbContainer, transferProgressBar, displayProgressBar, linkRemove);

that.startUpload(receiverId);

});


this.socket.on('server_receiver_left', function (receiverId) {
var receiverInfo = that.receiverInfos[receiverId];
receiverInfo.deactivate(true);
var progressBarContainer = receiverInfo.progressBarContainer;
progressBarContainer.empty();
progressBarContainer.append($("<p>").addClass("text-error").html("Receiver left before end of transfer"));
receiverInfo.removeLinkContainer.show();
jdNotif.notify("Something is wrong", "Apparently your friend left before the transfer was over");
that.transfertEnded(receiverId, true, "Apparently your friend left before the transfer was over")

});

Expand All @@ -128,16 +125,16 @@ SenderHandler.prototype = {
});

this.socket.on('server_transfer_complete', function (receiverId) {
that.transfertEnded(receiverId, false, "your friend correctly received your file", "File sent");
that.transfertEnded(receiverId, false, "your friend correctly received your file");
});


this.socket.on('server_transfer_timeout', function (receiverId) {
that.transfertEnded(receiverId, true, "your friend failed to download", "File not sent");
that.transfertEnded(receiverId, true, "your friend failed to download");
});

this.socket.on('server_transfer_disconnected', function (receiverId) {
that.transfertEnded(receiverId, true, "your friend failed to download", "File not sent");
that.transfertEnded(receiverId, true, "your friend failed to download");
});
},

Expand Down Expand Up @@ -179,19 +176,30 @@ SenderHandler.prototype = {

displayProgress: function (receiverId, percent) {
debug("displayProgress - %s - %d", receiverId, percent);
var transferProgressBar = this.receiverInfos[receiverId].progressBar;
var receiver = this.receiverInfos[receiverId];
//update progress bar
transferProgressBar.attr('aria-valuenow', percent);
transferProgressBar.width(percent + '%');
transferProgressBar.html(percent + '%');
receiver.progressBar.attr('value', percent);
receiver.progressBar.attr('aria-valuenow', percent);
receiver.displayProgressBar.html(percent + '%');
},

transfertEnded: function (receiverId, isError, notif, message) {
transfertEnded: function (receiverId, isError, notif) {
var receiverInfo = this.receiverInfos[receiverId];
receiverInfo.deactivate(isError);
var progressBarContainer = receiverInfo.progressBarContainer;
var spanResultProperties = {};
spanResultProperties["data-toggle"] = "tooltip";
spanResultProperties["data-placement"] = "right";
spanResultProperties["title"] = isError? "Transfer failed" : "Transfer successful";
var spanResult = $("<span>", spanResultProperties)
.addClass(isError? "icon-Thumb-down" : "icon-Thumb-up")
.addClass("big-icon");
progressBarContainer.empty();
progressBarContainer.append($("<p>").addClass(isError ? "text-danger" : "text-success").html(message));
progressBarContainer.append($("<p>")
.addClass(isError ? "text-danger" : "text-success")
.append(spanResult)
);
spanResult.tooltip();
receiverInfo.removeLinkContainer.show();

jdNotif.notify("Transfer ended", notif);
Expand Down Expand Up @@ -260,16 +268,17 @@ function sendFile(isLocal) {


/******************************************************************/
function ReceiverInfo(progressBarContainer, progressBar, removeLinkContainer) {
this.init(progressBarContainer, progressBar, removeLinkContainer);
function ReceiverInfo(progressBarContainer, progressBar, displayProgressBar, removeLinkContainer) {
this.init(progressBarContainer, progressBar, displayProgressBar, removeLinkContainer);
};

ReceiverInfo.prototype = {
constructor: ReceiverInfo,
init: function (progressBarContainer, progressBar, removeLinkContainer) {
init: function (progressBarContainer, progressBar, displayProgressBar, removeLinkContainer) {
this.active = false;
this.stream = null;
this.progressBar = progressBar;
this.displayProgressBar = displayProgressBar;
this.progressBarContainer = progressBarContainer;
this.removeLinkContainer = removeLinkContainer;
},
Expand Down
14 changes: 14 additions & 0 deletions dao.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,20 @@ Dao.prototype.getSender = function (senderId, callback, notFoundCallback) {
this._checkDefined(this.senders[senderId], callback, notFoundCallback);
};

Dao.prototype.getSenderFromUri = function (uri, callback, notFoundCallback) {
debug("Searching sender for URI %s",uri);
for (var senderId in this.senders) {
debug("Testing sender id %s", senderId);
if (this.senders.hasOwnProperty(senderId) && this.senders[senderId].uri == uri) {
debug("sender found");
this._checkDefined(this.senders[senderId], callback, notFoundCallback);
return;
}
}
notFoundCallback();
};


Dao.prototype.eachSenders = function (callback) {
for (var senderId in this.senders) {
if (this.senders.hasOwnProperty(senderId)) {
Expand Down
Loading

0 comments on commit d23b3b9

Please sign in to comment.