Giter VIP home page Giter VIP logo

socketio-file-upload's Introduction

Socket.IO File Upload

This module provides functionality to upload files from a browser to a Node.JS server that runs Socket.IO. Throughout the process, if their browser supports WebSockets, the user will not submit a single HTTP request. Supports Socket.IO 0.9 and higher.

The intended audience are single-page web apps, but other types of Node.JS projects may benefit from this library.

Since version 0.4, this module also supports monitoring file upload progress.

The module is released under the X11 open-source license.

Node.js CI Known Vulnerabilities npm version

Quick Start

Navigate to your project directory and run:

$ npm install --save socketio-file-upload

In your Express app, add the router like this (if you don't use Express, read the docs below):

var siofu = require("socketio-file-upload");
var app = express()
    .use(siofu.router)
    .listen(8000);

On a server-side socket connection, do this:

io.on("connection", function(socket){
    var uploader = new siofu();
    uploader.dir = "/path/to/save/uploads";
    uploader.listen(socket);
});

The client-side script is served at /siofu/client.js. Include it like this:

<script src="/siofu/client.js"></script>

If you use browserify, just require it like this:

var SocketIOFileUpload = require('socketio-file-upload');

The module also supports AMD; see the docs below for more information.

Then, in your client side app, with this HTML:

<input type="file" id="siofu_input" />

Just do this in JavaScript:

var socket = io.connect();
var uploader = new SocketIOFileUpload(socket);
uploader.listenOnInput(document.getElementById("siofu_input"));

That's all you need to get started. For the detailed API, continue reading below. A longer example is available at the bottom of the readme.

Table of Contents

Client-Side API

The client-side interface is inside the SocketIOFileUpload namespace. Include it with:

<script src="/siofu/client.js"></script>

If you're awesome and you use AMD/RequireJS, set up your paths config like this:

requirejs.config({
    paths: {
        "SocketIOFileUpload": "/siofu/client",
        // ...
    }
});

and then include it in your app like this:

define("app", ["SocketIOFileUpload"], function(SocketIOFileUpload){
    // ...
});

When instantiating an instance of the SocketIOFileUpload, pass a reference to your socket.

var instance = new SocketIOFileUpload(socket);

Public Properties and Methods

Each public property can be set up in an object passing at second parameter of the Siofu constructor:

var instance = new SocketIOFileUpload(socket);
instance.chunkSize = 1024 * 1000
// is the same that
var instance = new SocketIOFileUpload(socket, {
	chunkSize: 1024 * 1000
});

instance.listenOnInput(input)

When the user selects a file or files in the specified HTML Input Element, the library will begin to upload that file or those files.

JavaScript:

instance.listenOnInput(document.getElementById("file_input"));

HTML:

<label>Upload File: <input type="file" id="file_input" /></label>

All browsers tested support this method.

instance.listenOnDrop(element)

When the user drags and drops a file or files onto the specified HTML Element, the library will begin to upload that file or those files.

JavaScript:

instance.listenOnDrop(document.getElementById("file_drop"));

HTML:

<div id="file_drop">Drop Files Here</div>

In order to work, this method requires a browser that supports the HTML5 drag-and-drop interface.

instance.listenOnSubmit(submitButton, input)

Like instance.listenOnInput(input), except instead of listening for the "change" event on the input element, listen for the "click" event of a button.

JavaScript:

instance.listenOnSubmit(document.getElementById("my_button"), document.getElementById("file_input"));

HTML:

<label>Upload File: <input type="file" id="file_input" /></label>
<button id="my_button">Upload File</button>

instance.listenOnArraySubmit(submitButton, input[])

A shorthand for running instance.listenOnSubmit(submitButton, input) repeatedly over multiple file input elements. Accepts an array of file input elements as the second argument.

instance.prompt()

When this method is called, the user will be prompted to choose a file to upload.

JavaScript:

document.getElementById("file_button").addEventListener("click", instance.prompt, false);

HTML:

<button id="file_button">Upload File</button>

Unfortunately, this method does not work in Firefox for security reasons. Read the code comments for more information.

instance.submitFiles(files)

Call this method to manually submit an array of files. The argument can be either a FileList or an array of File objects.

instance.destroy()

Unbinds all events and DOM elements created by this instance of SIOFU.

Important Memory Note: In order to remove the instance of SIOFU from memory, you need to do at least three things:

  1. Remove all siofu.prompt event listeners and then
  2. Call this function and then
  3. Set this reference (and all references) to the instance to null

For example, if you created an instance like this:

// ...
var instance = new SocketIOFileUpload(socket);
myBtn.addEventListener("click", instance.prompt, false);
// ...

then you can remove it from memory like this:

myBtn.removeEventListener("click", instance.prompt, false);
instance.destroy();
instance = null;

instance.resetFileInputs = true

Defaults to true, which resets file input elements to their empty state after the user selects a file. If you do not reset the file input elements, if the user selects a file with the same name as the previous file, then the second file may not be uploaded.

instance.maxFileSize = null

Will cancel any attempt by the user to upload a file larger than this number of bytes. An "error" event with code 1 will be emitted if such an attempt is made. Defaults to a value of null, which does not enforce a file size limit.

To tell the client when they have tried to upload a file that is too large, you can use the following code:

siofu.addEventListener("error", function(data){
    if (data.code === 1) {
        alert("Don't upload such a big file");
    }
});

For maximum security, if you set a maximum file size on the client side, you should also do so on the server side.

instance.chunkSize = 100 KiB

The size of the file "chunks" to be loaded at a time. This enables you to monitor the upload progress with a progress bar and the "progress" event (see below).

The default value is 100 KiB, which is specified as

instance.chunkSize = 1024 * 100;

Setting this parameter to 0 disables chunking of files.

instance.useText = false

Defaults to false, which reads files as an octet array. This is necessary for binary-type files, like images.

Set to true to read and transmit files as plain text instead. This will save bandwidth if you expect to transmit only text files. If you choose this option, it is recommended that you perform a filter by returning false to a start event if the file does not have a desired extension.

instance.useBuffer = true

Starting with Socket.IO 1.0, binary data may now be transmitted through the Web Socket. Begining with SIOFU version 0.3.2 (December 17, 2014), this option is enabled by default. To support older versions of Socket.IO (e.g. version 0.9.x), set this option to false, which transmits files as base 64-encoded strings.

Advantages of enabling this option:

  • Less overhead in the socket, since base 64 increases overhead by approximately 33%.
  • No serialization and deserialization into and out of base 64 is required on the client and server side.

Disadvantages of enabling this option:

  • Transmitting buffer types through a WebSocket is not supported in older browsers.
  • This option is relatively new in both Socket.IO and Socket.IO File Upload and has not been rigorously tested.

As you use this option, please leave feedback.

instance.serializeOctets = false

This method is experimental, and has been deprecated in Socket.IO File Upload as of version 0.3 in favor of instance.useBuffer.

Defaults to false, which transmits binary files as Base 64 data (with a 33% overhead).

Set to true to instead transmit the data as a serialized octet array. This will result in an overhead of over 1000% (not recommended for production applications).

Note: This option is not supported by Firefox.

instance.topicName = "siofu"

Customize the name of the topic where Siofu emit message. Need to be the same that the one specified in the server options.

Can be used in team with instance.wrapData and instance.exposePrivateFunction to use a topic already used for something else.

instance.wrapData = false

By default Siofu client sends data the server on a different topic depending of the progress of the upload:

siofu_start
siofu_progress
siofu_done

And events received from the server to the client:

siofu_ready
siofu_chunk
siofu_complete
siofu_error

If wrapData is set to true, Siofu will use only one topic specified by instance.topicName and wrap the data into a parent message.

The following examples are example settings for the client. ⚠️ IF YOU USE wrapData ON THE CLIENT, YOU MUST ALSO USE IT ON THE SERVER. ⚠️

ex:

// wrapData false:
{
	id: id,
	success: success,
	detail: fileInfo.clientDetail
}
// wrapData true
{
	action: 'complete',
	message: {
		id: id,
		success: success,
		detail: fileInfo.clientDetail
	}
}

You can personalise the 'action' and 'message' key by passing a object to wrapData instance. The settings on the server should be the inverse of the settings on the client. For example, if the client has wrapData.wrapKey.message = "data", then the server should have wrapData.unwrapKey.message = "data".

instance.wrapData = {
	wrapKey: {
		action: 'actionType',
		message: 'data'
	},
	unwrapKey: {
		action: 'actionType',
		message: 'message'
	}
}
// Send a message like this:
{
	actionType: 'complete',
	data: {
		id: id,
		success: success,
		detail: fileInfo.clientDetail
	}
}
// Expect message like this from the server:
{
	actionType: 'complete',
	message: {
		id: id,
		success: success,
		detail: fileInfo.clientDetail
	}
}

It's also possible to add additional data (for strongly typed topic or secure pipeline or acknowledgement):

instance.wrapData = {
	adtionalData: {
		userId: '123456',
	},
}
// Send a message like this:
{
	userId: '123456',
	action: 'complete',
	message: {
		id: id,
		success: success,
		detail: fileInfo.clientDetail
	}
}

instance.exposePrivateFunction = false

If true this will expose some functions used in intern to personalize action on the topic. This is used alongside with wrapData to add custom check or logic before process the file upload. If true you will have access to:

instance.chunckCallback
instance.readyCallback
instance.completCallback
instance.errorCallback

Events

Instances of the SocketIOFileUpload object implement the W3C EventTarget interface. This means that you can do:

  • instance.addEventListener("type", callback)
  • instance.removeEventListener("type", callback)
  • instance.dispatchEvent(event)

The events are documented below.

choose

The user has chosen files to upload, through any of the channels you have implemented. If you want to cancel the upload, make your callback return false.

Event Properties
  • event.files an instance of a W3C FileList object

start

This event is fired immediately following the choose event, but once per file. If you want to cancel the upload for this individual file, make your callback return false.

Event Properties
  • event.file an instance of a W3C File object

progress

Part of the file has been loaded from the file system and ready to be transmitted via Socket.IO. This event can be used to make an upload progress bar.

You can compute the percent progress via event.bytesLoaded / event.file.size

Event Properties
  • event.file an instance of a W3C File object
  • event.bytesLoaded the number of bytes that have been loaded into memory
  • event.name the filename to which the server saved the file

load

A file has been loaded into an instance of the HTML5 FileReader object and has been transmitted through Socket.IO. We are awaiting a response from the server about whether the upload was successful; when we receive this response, a complete event will be dispatched.

Event Properties
  • event.file an instance of a W3C File object
  • event.reader an instance of a W3C FileReader object
  • event.name the filename to which the server saved the file

complete

The server has received our file.

Event Properties
  • event.file an instance of a W3C File object
  • event.success true if the server-side implementation ran without error; false otherwise
  • event.detail The value of file.clientDetail on the server side. Properties may be added to this object literal during any event on the server side.

error

The server encountered an error.

Event Properties
  • event.file an instance of a W3C File object
  • event.message the error message
  • event.code the error code, if available

Server-Side API

The server-side interface is contained within an NPM module. Require it with:

var SocketIOFileUpload = require("socketio-file-upload");

Static Properties and Methods

SocketIOFileUpload.listen(app)

If you are using an HTTP server in Node, pass it into this method in order for the client-side JavaScript file to be served.

var app = http.createServer( /* your configurations here */ ).listen(80);
SocketIOFileUpload.listen(app);

SocketIOFileUpload.router

If you are using Connect-based middleware like Express, pass this value into the middleware.

var app = express()
            .use(SocketIOFileUpload.router)
            .use( /* your other middleware here */ )
            .listen(80);

Public Properties and Methods

instance.listen(socket)

Listen for uploads occuring on this Socket.IO socket.

io.sockets.on("connection", function(socket){
    var uploader = new SocketIOFileUpload();
    uploader.listen(socket);
});

instance.abort(id, socket)

Aborts an upload that is in progress. Example use case:

uploader.on("start", function(event){
    if (/\.exe$/.test(event.file.name)) {
        uploader.abort(event.file.id, socket);
    }
});

instance.dir = "/path/to/upload/directory"

If specified, the module will attempt to save uploaded files in this directory. The module will intelligently suffix numbers to the uploaded filenames until name conflicts are resolved. It will also sanitize the filename to help prevent attacks.

The last-modified time of the file might be retained from the upload. If this is of high importance to you, I recommend performing some tests, and if it does not meet your needs, submit an issue or a pull request.

instance.mode = "0666"

Use these UNIX permissions when saving the uploaded file. Defaults to 0666.

instance.maxFileSize = null

The maximum file size, in bytes, to write to the disk. If file data is received from the client that exceeds this bound, the data will not be written to the disk and an "error" event will be thrown. Defaults to null, in which no maximum file size is enforced.

Note that the other events like "progress", "complete", and "saved" will still be emitted even if the file's maximum allowed size had been exceeded. However, in those events, event.file.success will be false.

instance.emitChunkFail = false

Whether or not to emit an error event if a progress chunk fails to finish writing. In most cases, the failure is a harmless notification that the file is larger than the internal buffer size, but it could also mean that the file upload triggered an ENOSPC error. It may be useful to enable this error event if you are concerned about uploads running out of space.

instance.uploadValidator(event, callback)

Can be overridden to enable async validation and preparing.

uploader.uploadValidator = function(event, callback){
    // asynchronous operations allowed here; when done,
    if (/* success */) {
        callback(true);
    } else {
        callback(false);
    }
};

Events

Instances of SocketIOFileUpload implement Node's EventEmitter interface. This means that you can do:

  • instance.on("type", callback)
  • instance.removeListener("type", callback)
  • instance.emit("type", event)
  • et cetera.

The events are documented below.

start

The client has started the upload process, and the server is now processing the request.

Event Properties
  • event.file An object containing the file's name, mtime, encoding, meta, success, bytesLoaded, and id. Note: encoding is either "text" if the file is being transmitted as plain text or "octet" if it is being transmitted using an ArrayBuffer. Note: In the "progress", "complete", "saved", and "error" events, if you are letting the module save the file for you, the file object will contain two additional properties: base, the new base name given to the file, and pathName, the full path at which the uploaded file was saved.

progress

Data has been received from the client.

Event Properties
  • event.file The same file object that would have been passed during the start event earlier.
  • event.buffer A buffer containing the data received from the client

complete

The transmission of a file is complete.

Event Properties
  • event.file The same file object that would have been passed during the start event earlier.
  • event.interrupt true if the client said that the data was interrupted (not completely sent); false otherwise

saved

A file has been saved. It is recommended that you check event.file.success to tell whether or not the file was saved without errors.

In this event, you can safely move the saved file to a new location.

Event Properties
  • event.file The same file object that would have been passed during the start event earlier.

error

An error was encountered in the saving of the file.

Event Properties
  • event.file The same file object that would have been passed during the start event earlier.
  • event.error The I/O error that was encountered.

Adding Meta Data

It is sometimes useful to add metadata to a file prior to uploading the file. You may add metadata to a file on the client side by setting the file.meta property on the File object during the "choose" or "start" events. You may also add metadata to a file on the server side by setting the file.clientDetail property on the fileInfo object during any of the server-side events.

Client to Server Meta Data

To add meta data to an individual file, you can listen on the "start" event as shown below.

// client side
siofu.addEventListener("start", function(event){
    event.file.meta.hello = "world";
});

The data is then available on the server side as follows.

// server side
uploader.on("saved", function(event){
    console.log(event.file.meta.hello);
});

You can also refer back to your meta data at any time on the client side by referencing the same event.file.meta object literal.

Server to Client Meta Data

You can add meta data on the server. The meta data will be available to the client on the "complete" event on the client as shown below.

// server side
siofuServer.on("saved", function(event){
    event.file.clientDetail.hello = "world";
});

The information saved in event.file.clientDetail will be available in event.detail on the client side.

// client side
siofu.addEventListener("complete", function(event){
    console.log(event.detail.hello);
});

Example

This example assumes that you are running your application via the Connect middleware, including Express. If you are using a middleware that is not Connect-based or Node-HTTP-based, download the client.js file from the project repository and serve it on the path /siofu/client.js. Alternatively, you may contribute an adapter for your middleware to this project and submit a pull request.

Server Code: app.js

// Require the libraries:
var SocketIOFileUpload = require('socketio-file-upload'),
    socketio = require('socket.io'),
    express = require('express');

// Make your Express server:
var app = express()
    .use(SocketIOFileUpload.router)
    .use(express.static(__dirname + "/public"))
    .listen(80);

// Start up Socket.IO:
var io = socketio.listen(app);
io.sockets.on("connection", function(socket){

    // Make an instance of SocketIOFileUpload and listen on this socket:
    var uploader = new SocketIOFileUpload();
    uploader.dir = "/srv/uploads";
    uploader.listen(socket);

    // Do something when a file is saved:
    uploader.on("saved", function(event){
        console.log(event.file);
    });

    // Error handler:
    uploader.on("error", function(event){
        console.log("Error from uploader", event);
    });
});

Client Code: public/index.html

<!DOCTYPE html>
<html>
<head>
<title>Upload Files</title>
<script src="/siofu/client.js"></script>
<script src="/socket.io/socket.io.js"></script>

<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(){

    // Initialize instances:
    var socket = io.connect();
    var siofu = new SocketIOFileUpload(socket);

    // Configure the three ways that SocketIOFileUpload can read files:
    document.getElementById("upload_btn").addEventListener("click", siofu.prompt, false);
    siofu.listenOnInput(document.getElementById("upload_input"));
    siofu.listenOnDrop(document.getElementById("file_drop"));

    // Do something on upload progress:
    siofu.addEventListener("progress", function(event){
        var percent = event.bytesLoaded / event.file.size * 100;
        console.log("File is", percent.toFixed(2), "percent loaded");
    });

    // Do something when a file is uploaded:
    siofu.addEventListener("complete", function(event){
        console.log(event.success);
        console.log(event.file);
    });

}, false);
</script>

</head>
<body>

<p><button id="upload_btn">Prompt for File</button></p>
<p><label>Choose File: <input type="file" id="upload_input"/></label></p>
<div id="file_drop" dropzone="copy" title="drop files for upload">Drop File</div>

</body>
</html>

Future Work

First, I'm aware that this module currently lacks unit tests (mocha, etc). This is a problem that should be solved. I'm willing to accept PRs that add unit tests, or else one of these days when I have extra time I'll see if I can add them myself.

In addition, the following features would be useful for the module to support.

  1. Allow input of a file URL rather than uploading a file from your computer or mobile device.

As always PRs are welcome.

socketio-file-upload's People

Contributors

amontagu avatar artskydj avatar daneeveritt avatar dependabot[bot] avatar dev-tim avatar jcavandoli avatar luffs avatar maffoobristol avatar maxleiter avatar meelie avatar mritzco avatar senica avatar sffc avatar sjiep avatar snyk-bot avatar vote539 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

socketio-file-upload's Issues

Upload Interruption should trigger error for handling

When client socket disconnects or refresh happens on client side there should be an error on server. Is this the case? did I miss something in the documentation?
on.complete does not fire when file is upload is interrupted.

Include source mappings with minified version

It would be awesome if a source mapping could be included as well as the minified version so that issues that are thrown to the browser console can be correctly identified and traced, rather than getting stacks that just report x as a variable.

Show File

Sorry, but i'm newbie in this.

I think my code is ok.
When i select a file, the console show the Object.

How i can show the file on html?
I need upload a image and set this on css background.

Thx for help!

example code crashes server

When I try to run the example my server crashes:

 debug - websocket writing 1::
   debug - websocket writing 5:::{"name":"siofu_complete","args":[{"id":0,"success":false,"detail":{}}]}

events.js:73
        throw new Error("Uncaught, unspecified 'error' event.");
              ^
Error: Uncaught, unspecified 'error' event.
    at SocketIOFileUploadServer.EventEmitter.emit (events.js:73:15)
    at _uploadStart (/node_modules/socketio-file-upload/server.js:231:12)
    at _findFileName (/node_modules/socketio-file-upload/server.js:119:5)
    at _findFileNameWorker (h/node_modules/socketio-file-upload/server.js:94:7)
    at Object.oncomplete (fs.js:297:15)

This is happening in the browser

5:::{"name":"siofu_complete","args":[{"id":0,"success":false,"detail":{}}]}
75
20:55:33
5:::{"name":"siofu_start","args":[{"name":"test.svg","mtime":"2013-11-12T17:53:25.000Z","encoding":"octet","id":0}]}

I'm using exact example code. I think it is more a client side of problem?

Unable to get file to transfer

I am trying to use socketio-file-upload from a context menu item click event. I am calling myinstance.prompt(), the dialog comes up, I select a file, hit Open. The server emits a "siofu_ready", then nothing else happens. The file is created in the specified server side dir but with 0 bytes. No errors in the console. Help would be appreciated.

How do you submit files submitFiles() manually ?

Am I doing anything wrong ?

HTML

<input type="file" class="file-brows"
                 onchange="angular.element(this).scope().onChangeStartFileUpload(event)" >

JavaScript

   scope.onChangeStartFileUpload = function(event){
        var files = event.target.files;
        // upload.submitFiles(files[0]);
       // upload.submitFiles(files);
      };

Server side validation ?

How do I stop uploads if file doesn't meet file.type server side.
Giving Server ability to stop upload or proceed with upload.

Uploaded file with non-English letter is saved in undesirable way

Uploaded files with non-English letter are saved in undesirable way.

Server and browser were set to utf-8 character set.
% locale
LANG=ko_KR.UTF-8

server side console log is as followings

session.user : { username: 'bob' }
session.user.username : bob
debug - emitting heartbeat for client 0byjQVSiXUjpmcUVYThz
debug - websocket writing 2::
debug - set heartbeat timeout for client 0byjQVSiXUjpmcUVYThz
debug - got heartbeat packet
debug - cleared heartbeat timeout for client 0byjQVSiXUjpmcUVYThz
debug - set heartbeat interval for client 0byjQVSiXUjpmcUVYThz
debug - websocket writing 5:::{"name":"siofu_ready","args":[{"id":0,"name":"-0"}]}
File saved !!
{ name: '소야도 포인트.JPG',
mtime: Tue Nov 27 2012 16:58:53 GMT+0900 (KST),
encoding: 'octet',
clientDetail: {},
id: 0,
base: '
-0',
pathName: '/var/uploads/-0.JPG',
writeStream:
{ writableState:
{ highWaterMark: 16384,
objectMode: false,
needDrain: true,
ending: true,
ended: true,
finished: true,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
sync: false,
bufferProcessing: false,
onwrite: [Function],
writecb: null,
writelen: 0,
buffer: [] },
writable: true,
domain: null,
events: { open: [Function], error: [Function] },
maxListeners: 10,
path: '/var/uploads/
-0.JPG',
fd: null,
flags: 'w',
mode: '0666',
start: undefined,
pos: undefined,
bytesWritten: 169291,
closed: true } }
debug - websocket writing 5:::{"name":"news","args":[{"name":"소야도 포인트.JPG","mtime":"2012-11-27T07:58:53.000Z","encoding":"octet","clientDetail":{},"id":0,"base":"
-0","pathName":"/var/uploads/-0.JPG","writeStream":{"writableState":{"highWaterMark":16384,"objectMode":false,"needDrain":true,"ending":true,"ended":true,"finished":true,"decodeStrings":true,"defaultEncoding":"utf8","length":0,"writing":false,"sync":false,"bufferProcessing":false,"writecb":null,"writelen":0,"buffer":[]},"writable":true,"domain":null,"events":{},"maxListeners":10,"path":"/var/uploads/_-0.JPG","fd":null,"flags":"w","mode":"0666","bytesWritten":169291,"closed":true}}]}
debug - websocket writing 5:::{"name":"siofu_complete","args":[{"id":0,"success":true,"detail":{}}]}
debug - emitting heartbeat for client 0byjQVSiXUjpmcUVYThz


screen-captured browser console log
image

Let me know how to fix this problem, Thank you : -)

submitFiles() should accept objects of type `File` or an array of `Files`, not just FileList

I'm bouncing the output from Dropzone.js and specifically react-dropzone into SIOFU's instance.submitFiles(), but it seems to only accept objects of type FileList, whilst dropzone's onDrop events pass through a File, meaning that it's not compatible. I thought perhaps I could send the File array-wrapped, or even instantiate a new FileList([File]) or something, but that seems to not be supported. Some things when sent will chuck out an error, but some things will just silently fail. On the whole it seems to be a bit confusing as to how exactly it should work.

What are your thoughts on this?

Ta!
Matt

Emitting progress updates question

New to node and socket.io but this looks promising :)
How would I use the progress event to send the client regular file upload progress messages?

Benchmark

This lib is very similar to mine, I have tested the who side by side to see if there is any speed difference. It seems they are near identical in speed (for me ~4 megabytes a second uploaded), in my tests I am uploading over a 10gig network, I tried disabling the server from writing to file on both libraries and found that the speed did not change, my theory is that the client browsers file.slice > file.read* is the bottle neck.

Has anyone else looked into this? Is anyone getting much better than 3-4 MB/s ?

*I use 'readAsBinaryString', this lib uses 'readAsText' and 'readAsArrayBuffer' (I found no real speed difference between the 3 methods)

*My speed calcluation is:

/**

  • this get the time since the last push, scales the time and speed to per second values
    */

        var timeNow = new Date();
        if (File.lastTime) {
            var difference = timeNow.getTime() - File.lastTime.getTime();
            var seconds = Math.floor(difference * 1000);
            var scale = 1 / seconds;
            var scaledSize = CHUNK_SIZE * scale;
            File.speed = scaledSize.toFixed(2) // <-- MB/s
    
    
        }
    

    ...
    //do slice & read file, etc.

        File.lastTime = timeNow;
    

Can't upload file in Android Crosswalk when use plugin File or File-transfer

Hello vote539,

Have a nice day!

I have found a bug in hybrid mobile app that makes the socketio-file-upload don't work.

When I add plugin org.apache.cordova.file or org.apache.cordova.file-transfer to my app (ionic crosswalk android app), I can't upload my file to server but can choose file.

After some researchs (compared between Android and Firefox browser in Dekstop,... ), I found that the FileReader object in Android crosswalk has quite differences, it was changed by default, but you can find an attribute "_realReader"!

Yeah, from that point, I add following lines before line "// Calculate chunk size" and it works :)

if (reader._realReader)
        reader = reader._realReader;

Thank for your awesome plugin!

Manually invoke upload instance.submitFiles(files)

Hi
I'm trying to drag a image from element on the screen or from a remote URL into drop element of siofu. Manually invoke upload am I going down the right path or is there a different way to handle this ?

 angular.element(currentElement).bind('drop',function(event){
      var imageURL = event.dataTransfer.getData('text');
      var xhr = new XMLHttpRequest();
      xhr.open('GET', imageURL, true);
      xhr.responseType = 'blob';
      xhr.onload = function(e) {
      if (this.status === 200) {
         var myBlob = xhr.response;
         var fileObj = new File([myBlob],'image.jpg',{});
         siofu.submitFiles(fileObj);
      }
  };

SocketIOFileUploadServer not accessible in mobile browser/ webview

i tried to connect socket in android, windows mobile browser , in which socket is connected but the SOFU , i using submit button event to upload files, which works well on web browser but not in mobiles,
how to make it work with mobile as well, please suggest any solution to this

code snap for it:

appjs

index

File mtime detected as invalid.

I'm having a strange issue where file uploads are being marked as having an invalid mtime when they are uploaded. This causes the files to use UNIX epoch as the timestamp (which is a bit undesirable).

This is an example of the output of the saved event on the server.

{ file: 
   { name: 'Microsoft Word - Lab 5 Lists.pdf',
     mtime: Invalid Date,
     encoding: 'octet',
     clientDetail: {},
     meta: { path: '', identifier: 'vqrn05pdn7m' },
     id: 0,
     size: 72118,
     bytesLoaded: 72118,
     success: true,
     base: 'Microsoft Word - Lab 5 Lists',
     pathName: '/srv/daemon-data/ptdl-mumble_e1ltb/data/Microsoft Word - Lab 5 Lists.pdf',
     writeStream: 
      WriteStream {
        _writableState: [Object],
        writable: true,
        domain: null,
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        path: '/srv/daemon-data/ptdl-mumble_e1ltb/data/Microsoft Word - Lab 5 Lists.pdf',
        fd: 20,
        flags: 'w',
        mode: '0666',
        start: undefined,
        autoClose: true,
        pos: undefined,
        bytesWritten: 72118 } } }

Here is the output of event.file during the progress step in the browser.

lastModified: 1476111825000
meta: {path: "", identifier: "vqrn05pdn7m"}
name: "Microsoft Word - Lab 5 Lists.pdf"
size: 72118
type: "application/pdf"

Same output on the complete event in the browser.

lastModified: 1476111825000
meta: {path: "", identifier: "vqrn05pdn7m"}
name: "Microsoft Word - Lab 5 Lists.pdf"
size: 72118
type: "application/pdf"

Interestingly, if you refresh the page before the file is done uploading the last modified time is correct.

Allow overwriting files

Unless I'm not seeing the option, it seems there is no way to allow the uploader to overwrite a file if it already exists.

Uploaded files not saved ...

Trying to use "socketio-file-upload" in my project. Client side events fired, server side events also fired besides "progress" events ... Files created in upload directory on the server side, but uploaded files are empty. Each time a new file uploaded, server side events are multiplied.
Appreciate any help!

Thank you!

Problem solved ... Working in browsers which are able create instance of HTML5 FileReader object.

Permission error 34 - uploader.dir = " /var/www/vhosts/chattet.de/maiwell.chattet.de/uploads";

i've tried chmod 755. chmod 777 user:usergroup www-data:www-data nothing is working, why?

on an other server it's working

0|app | Error from uploader { file:
0|app | { name: 'a.png',
0|app | mtime: Sat Sep 02 2017 13:31:44 GMT+0200 (CEST),
0|app | encoding: 'octet',
0|app | clientDetail: {},
0|app | meta: {},
0|app | id: 3,
0|app | size: 8380,
0|app | bytesLoaded: 0,
0|app | success: true },
0|app | error:
0|app | { [Error: ENOENT, open ' /var/www/vhosts/chattet.de/maiwell.chattet.de/uploads/a.png']
0|app | errno: 34,
0|app | code: 'ENOENT',
0|app | path: ' /var/www/vhosts/chattet.de/maiwell.chattet.de/uploads/a.png' },
0|app | memo: 'computing file name' }

Handle missing directory

Currently if you attempt to upload into a path that does not exist the process simply quits with an error, as would be expected. It'd be nice if there was a way to either have the process create that folder, or to allow an event where I could check for the folder, and create it before the file starts trying to upload to that location.

File size limit on uploads?

Again, great stuff. This npm has proven to be incredibly useful to this point!

I am running into an issue that seems to be related to the socket timing out when I upload lager files - say, more than 25MB. I know I know - huge for the internet but I'm combining this with fluent-ffmpeg to convert and edit video files so in some cases they can get pretty large.

Any idea on how to force the socket to not time out? Is this a socket.io or file-upload thing - if socket, is there a way to over-ride it to stay active?

Uploads tangled between clients

Some images I upload on one client get uploaded on the other clients browser. I'm not sure what is causing it. I've tried putting the server lines where the documentation said to put them
var uploader = new siofu();
uploader.dir = 'images';
uploader.listen(socket);
And also I tried putting them in an event that only fires once when the client connects. Neither worked.

Drag Events

listenOnDrop() does this method override the drop event.

Want to set custom values to "event" after saving file

Actually I tried to save file with current time (say 1384637442348.jpg) as name instead of original file name(XXXXX.jpg).
So, I set file name in "start". But, while getting event in "complete" (client side) always returns event with old name(XXXXX.jpg) only. Also, I want to add some additional info to the event once file saved on server.

Here my code goes,

//Server side
uploader.on("start", function(event){
console.log(":::::::::Start::::::::");
event.file.name = new Date().getTime()+".jpg";
console.log(event);
});
uploader.on("saved", function(event){
console.log(":::::::::Saved::::::::");
event.actualName = event.file.pathName; //Custom Value
console.log(event);
});

//Client side
siofu.addEventListener("complete", function(event){
console.log(event.success);
console.log(event.file);
});

//Server Log:
:::::::::Start::::::::
{ file:
{ name: '1384637442348.jpg',
mtime: Fri May 24 2013 17:14:48 GMT+0530 (IST),
encoding: 'octet',
id: 0 } }
:::::::::Start::::::::
{ file:
{ name: '1384637442348.jpg',
mtime: Fri May 24 2013 17:14:48 GMT+0530 (IST),
encoding: 'octet',
id: 0,
base: '1384637442348',
pathName: '/Users/mymac/Node/uploadedFiles/1384637442348.jpg',
writeStream:
{ _writableState: [Object],
writable: true,
domain: null,
_events: [Object],
_maxListeners: 10,
path: '/Users/mymac/Node/uploadedFiles/1384637442348.jpg',
fd: null,
flags: 'w',
mode: '0666',
start: undefined,
pos: undefined,
bytesWritten: 50022,
closed: true } },
actualName: '/Users/mymac/Node/uploadedFiles/1384637442348.jpg' }

//Client Log:
true
File { size=256963, type="image/jpeg", name="XXXXX.jpg", more...}

Can you please help me to solve it in some other way? Correct me if i did anything wrong.

destroy method

That all worked fine and dandy but then I was running into an issue where it was very difficult to remove the event listeners. To resolve this, I added the following to client.js:

/**

  • Destroys the old listeners and allows me to refresh new ones.
    */
    this.destroy = function(){

callbacks = {};
uploadedFiles = [];
readyCallbacks = [];
}

This allows me to do a hard reset of siofu when I load a new page or new content by calling it from the template when it is being unloaded. This also resolved an issue where if I did several edits on a page (moved another image to the upload spot) both would appear (in my case, I only want one).

Renaming your file before saving

maybe i don't understand how this package works very well. i have spent time to see how i can rename a file before saving it to a folder but couldn't figure it out. please if there is way to achieve this let me know. will be glad to hear your feedback ,thanks

Clear input value after upload

input does not trigger change event when the value is the same. To upload the same file twice the input value has to be cleared.

Microsoft Edge file object missing lastModified

This is not an issue with socketio-file-upload, but is an issue others may run into when uploading files.

I found that my Microsoft Edge users would end up with files on my server with junk timestamps. In my case, I have a process that rsyncs the files to another location and preserves timestamps. rsync would fail with a message like the one below--substitute your file name.

Time value of %s truncated on receiver.

The issue is that Edge does not follow the spec for the File Object as explained here:
https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/4155006/

In short, the object is missing the "lastModified" property that normally holds the unix time value. In my own code, I was able to account for this by adding this bit of code in my function where I handle each file object:

if (!file.lastModified) { file.lastModified = file.lastModifiedDate.getTime(); }

Arguably, socketio-file-upload client could do this same thing internally.

Restrict File Size Limit While Choosing File

i want to restrict the user not to select file size more than 10mb,
any suggestion to my requirment.

Suggestion to implement in this "socketio-file-upload" module
1>thumbnil for each uploaded file
2>upload only image file/ or any other by extension
3>download files in socket

[FIX] Client to Server Meta Data do not work

Hi,

I'm trying to send same metadata from client to server and I get the following error.

TypeError: event.file.meta is undefined
event.file.meta.hello = "world";

My client-side code:

uploader.addEventListener("start", function(event){
    event.file.meta.hello = "world";
});

Everything else works just fine, beside this one.
If I set clientDetail from server to client, it works.

I have also tried defining the meta data like this:

event.file = {
            'meta' : {
                'hello': world,
            }
        };
--- or ---
event.file.meta = {
      'hello' : world;
};

...but on server side I get "undefined" when trying to access these values with event.file.meta.hello

FIX

It seems that npm install --save socketio-file-upload does not install the latest github version and all js files are smaller in size than the original github ones.
So, unless the node package is not up-to-date, it would be better to manually copy files from github repo...

Server crashes with: ENOENT, utime error

Hi,

We have an application running stable for several months but today we got a server crash because of an ENOENT, utime error, from the file server.js line 156

After looking at the code I can see it's related to changing the file modified time:

fs.utimes(...
    if (err) { ...
        throw err

Even tough the throw is inside a try-catch block the application crashed. Interestingly the file was properly uploaded, moved and the time stamp was actually updated.

I understand it's mysterious than the try-catch block failed to do its job, but as it seems to be a small error does it justify risking a throw?

Any clue on how to prevent it, or should I send a pull request replacing the throw with a log message?

Thanks!

Undefined is not a function - client.js: 498

Appears sporadically when I'm trying to upload images, haven't been able to perfectly recreate the environment that breaks it, but it fails on this line:

// CONSTRUCTOR: Listen to the "complete", "ready", and "error" messages on the socket.
socket.on("siofu_ready", function(data){
    readyCallbacks[data.id](data.name);
});

... it makes me think that for some reason data.id is sometimes undefined. I've used the api in the same way as in the documentation so I don't know what's going on.

Cheers, Matt.

Multiple Dropzones

I can only use ID for drop event
I need to use class so I can have multiple dope arias on the screen.
is this possible ?

Specify a custom directory for each upload

The example for uploadValidator sets the global uploader.dir property on the fly, which can have a race condition for two simultaneous uploads. A better approach would be to allow every file to have its own custom directory to override the global setting.

See #58 and #60

Binary Data Transmission

Socket.IO 1.0 now supports binary data transmission through the WebSocket. The next release of Socket.IO File Upload will support transmitting files through this new architecture.

You can enable file transfer with buffers by setting instance.useBuffer = true on the client side.

As you use this new feature, leave feedback here. In a future release of Socket.IO File Upload, this option may default to "true" rather than to "false".

I can't set the quantity of files that can be uploaded per time

When I select something around 20 files, it send chunks for all the files. So if I lose internet connection, all the upload progress is aborted and I'll get no complete files in the server.

Something like this could be implemented? Setting, per example, 2 files per time (for sending chunks). So when one of these 2 files is fully uploaded, the system start sending chunks for the next file.

Cordova app

has anyone gotten this to work with a cordova app/ionic? i am getting just a bunch of errors on it right now. lastly that "addEventListener is not a function"
from
var _listenTo = function (object, eventName, callback, bubble) {
object.addEventListener(eventName, callback, bubble);
_listenedReferences.push(arguments);
};
i havent attached anything to it yet, ive just done the new instantiate of it.

"var uploader = new SocketIOFileUpload(socket);"

The second question is doing it without the document watcher if possible, not sure if i can just send a file location to it yet, but only will worry about then when it doesn't error i suppose.

Thank you

Support for non-html5 browsers

Hi there, just a quick question.
I just read the readme file and noticed you mention html5 supporting browsers.
Is that requirement about file drag-and-drop or for this module to work?
Given socket.io works in ie7, can we assume this module works in ie7?

Uncaught DOMException: Failed to execute 'readAsArrayBuffer' on 'FileReader': The object is already busy reading Blobs.

A user reported that in Chrome on Windows 10 the following error is thrown which causes the progress indicator to read 100% done while network traffic continues in the background.

I'm not sure if this is fixed by #60 or not as I haven't updated our codebase to use anything past 0.5.0, but I can check on that later this week if that would help.

Uncaught DOMException: Failed to execute 'readAsArrayBuffer' on 'FileReader': The object is already busy reading Blobs.
    at x (<redacted>/js/vendor/upload/client.min.js:9:231)
    at Array.<anonymous> (<redacted>/js/vendor/upload/client.min.js:11:449)
    at n.<anonymous> (<redacted>/js/vendor/upload/client.min.js:15:179)
    at n.e.emit (<redacted>/js/vendor/socketio/socket.io.min.js:23:1606)
    at n.onevent (<redacted>/js/vendor/socketio/socket.io.min.js:22:31333)
    at n.onpacket (<redacted>/js/vendor/socketio/socket.io.min.js:22:30955)
    at n.<anonymous> (<redacted>/js/vendor/socketio/socket.io.min.js:23:2238)
    at n.e.emit (<redacted>/js/vendor/socketio/socket.io.min.js:23:1606)
    at n.ondecoded (<redacted>/js/vendor/socketio/socket.io.min.js:21:23673)
    at s.<anonymous> (<redacted>/js/vendor/socketio/socket.io.min.js:23:2238)
x @ client.min.js:9

Ability to cancel an upload in progress

How difficult would it be to provide a method to cancel an in-progress file upload? Dropzone.js offers this functionality: http://www.dropzonejs.com/#config-addRemoveLinks. I'm thinking something similar.

To understand why someone might want this, "accidentally" drop a folder with a dozen 500MB video files onto your application's dropzone. It would be nice if the user could click to cancel either individual files or all files.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.