A JavaScript library providing multiple simultaneous, stable, fault-tolerant and resumable/restartable file uploads via the HTML5 File API.

Overview

Flow.js Build Status Test Coverage Saucelabs Test Status Buy Me A Coffee

Flow.js is a JavaScript library providing multiple simultaneous, stable and resumable uploads via the HTML5 File API. (Demo)

The library is designed to introduce fault-tolerance into the upload of large files through HTTP. This is done by splitting each file into small chunks. Then, whenever the upload of a chunk fails, uploading is retried until the procedure completes. This allows uploads to automatically resume uploading after a network connection is lost either locally or to the server. Additionally, it allows for users to pause, resume and even recover uploads without losing state because only the currently uploading chunks will be aborted, not the entire upload.

Flow.js does not have any external dependencies other than the HTML5 File API. This is relied on for the ability to chunk files into smaller pieces. Currently, this means that support is limited to Firefox 4+, Chrome 11+, Safari 6+ and Internet Explorer 10+.

Samples and examples are available in the samples/ folder. Please push your own as Markdown to help document the project.

Can I see a demo?

Flow.js + angular.js file upload demo - ng-flow extension page https://github.com/flowjs/ng-flow

JQuery and node.js backend demo https://github.com/flowjs/flow.js/tree/master/samples/Node.js

How can I install it?

Download a latest build from https://github.com/flowjs/flow.js/releases it contains development and minified production files in dist/ folder.

or use npm:

npm install @flowjs/flow.js

or use bower:

bower install flow.js#~2

or use git clone

git clone https://github.com/flowjs/flow.js

How can I use it?

A new Flow object is created with information of what and where to post:

var flow = new Flow({
  target:'/api/photo/redeem-upload-token', 
  query:{upload_token:'my_token'}
});
// Flow.js isn't supported, fall back on a different method
if(!flow.support) location.href = '/some-old-crappy-uploader';

To allow files to be either selected and drag-dropped, you'll assign drop target and a DOM item to be clicked for browsing:

flow.assignBrowse(document.getElementById('browseButton'));
flow.assignDrop(document.getElementById('dropTarget'));

After this, interaction with Flow.js is done by listening to events:

flow.on('fileAdded', function(file, event){
    console.log(file, event);
});
flow.on('fileSuccess', function(file,message){
    console.log(file,message);
});
flow.on('fileError', function(file, message){
    console.log(file, message);
});

How do I set it up with my server?

Most of the magic for Flow.js happens in the user's browser, but files still need to be reassembled from chunks on the server side. This should be a fairly simple task and can be achieved in any web framework or language, which is able to receive file uploads.

To handle the state of upload chunks, a number of extra parameters are sent along with all requests:

  • flowChunkNumber: The index of the chunk in the current upload. First chunk is 1 (no base-0 counting here).
  • flowTotalChunks: The total number of chunks.
  • flowChunkSize: The general chunk size. Using this value and flowTotalSize you can calculate the total number of chunks. Please note that the size of the data received in the HTTP might be lower than flowChunkSize of this for the last chunk for a file.
  • flowTotalSize: The total file size.
  • flowIdentifier: A unique identifier for the file contained in the request.
  • flowFilename: The original file name (since a bug in Firefox results in the file name not being transmitted in chunk multipart posts).
  • flowRelativePath: The file's relative path when selecting a directory (defaults to file name in all browsers except Chrome).

You should allow for the same chunk to be uploaded more than once; this isn't standard behaviour, but on an unstable network environment it could happen, and this case is exactly what Flow.js is designed for.

For every request, you can confirm reception in HTTP status codes (can be change through the permanentErrors option):

  • 200, 201, 202: The chunk was accepted and correct. No need to re-upload.
  • 404, 415. 500, 501: The file for which the chunk was uploaded is not supported, cancel the entire upload.
  • Anything else: Something went wrong, but try reuploading the file.

Handling GET (or test() requests)

Enabling the testChunks option will allow uploads to be resumed after browser restarts and even across browsers (in theory you could even run the same file upload across multiple tabs or different browsers). The POST data requests listed are required to use Flow.js to receive data, but you can extend support by implementing a corresponding GET request with the same parameters:

  • If this request returns a 200, 201 or 202 HTTP code, the chunks is assumed to have been completed.
  • If request returns a permanent error status, upload is stopped.
  • If request returns anything else, the chunk will be uploaded in the standard fashion.

After this is done and testChunks enabled, an upload can quickly catch up even after a browser restart by simply verifying already uploaded chunks that do not need to be uploaded again.

Full documentation

Flow

Configuration

The object is loaded with a configuration options:

var r = new Flow({opt1:'val', ...});

Available configuration options are:

  • target The target URL for the multipart POST request. This can be a string or a function. If a function, it will be passed a FlowFile, a FlowChunk and isTest boolean (Default: /)
  • singleFile Enable single file upload. Once one file is uploaded, second file will overtake existing one, first one will be canceled. (Default: false)
  • chunkSize The size in bytes of each uploaded chunk of data. This can be a number or a function. If a function, it will be passed a FlowFile. The last uploaded chunk will be at least this size and up to two the size, see Issue #51 for details and reasons. (Default: 1*1024*1024, 1MB)
  • forceChunkSize Force all chunks to be less or equal than chunkSize. Otherwise, the last chunk will be greater than or equal to chunkSize. (Default: false)
  • simultaneousUploads Number of simultaneous uploads (Default: 3)
  • fileParameterName The name of the multipart POST parameter to use for the file chunk (Default: file)
  • query Extra parameters to include in the multipart POST with data. This can be an object or a function. If a function, it will be passed a FlowFile, a FlowChunk object and a isTest boolean (Default: {})
  • headers Extra headers to include in the multipart POST with data. If a function, it will be passed a FlowFile, a FlowChunk object and a isTest boolean (Default: {})
  • withCredentials Standard CORS requests do not send or set any cookies by default. In order to include cookies as part of the request, you need to set the withCredentials property to true. (Default: false)
  • method Method to use when POSTing chunks to the server (multipart or octet) (Default: multipart)
  • testMethod HTTP method to use when chunks are being tested. If set to a function, it will be passed a FlowFile and a FlowChunk arguments. (Default: GET)
  • uploadMethod HTTP method to use when chunks are being uploaded. If set to a function, it will be passed a FlowFile and a FlowChunk arguments. (Default: POST)
  • allowDuplicateUploads Once a file is uploaded, allow reupload of the same file. By default, if a file is already uploaded, it will be skipped unless the file is removed from the existing Flow object. (Default: false)
  • prioritizeFirstAndLastChunk Prioritize first and last chunks of all files. This can be handy if you can determine if a file is valid for your service from only the first or last chunk. For example, photo or video meta data is usually located in the first part of a file, making it easy to test support from only the first chunk. (Default: false)
  • testChunks Make a GET request to the server for each chunks to see if it already exists. If implemented on the server-side, this will allow for upload resumes even after a browser crash or even a computer restart. (Default: true)
  • preprocess Optional function to process each chunk before testing & sending. To the function it will be passed the chunk as parameter, and should call the preprocessFinished method on the chunk when finished. (Default: null)
  • changeRawDataBeforeSend Optional function to change Raw Data just before the XHR Request can be sent for each chunk. To the function, it will be passed the chunk and the data as a Parameter. Return the data which will be then sent to the XHR request without further modification. (Default: null). This is helpful when using FlowJS with Google Cloud Storage. Usage example can be seen #276. (For more, check issue #170).
  • initFileFn Optional function to initialize the fileObject. To the function it will be passed a FlowFile and a FlowChunk arguments.
  • readFileFn Optional function wrapping reading operation from the original file. To the function it will be passed the FlowFile, the startByte and endByte, the fileType and the FlowChunk.
  • generateUniqueIdentifier Override the function that generates unique identifiers for each file. (Default: null)
  • maxChunkRetries The maximum number of retries for a chunk before the upload is failed. Valid values are any positive integer and undefined for no limit. (Default: 0)
  • chunkRetryInterval The number of milliseconds to wait before retrying a chunk on a non-permanent error. Valid values are any positive integer and undefined for immediate retry. (Default: undefined)
  • progressCallbacksInterval The time interval in milliseconds between progress reports. Set it to 0 to handle each progress callback. (Default: 500)
  • speedSmoothingFactor Used for calculating average upload speed. Number from 1 to 0. Set to 1 and average upload speed wil be equal to current upload speed. For longer file uploads it is better set this number to 0.02, because time remaining estimation will be more accurate. This parameter must be adjusted together with progressCallbacksInterval parameter. (Default 0.1)
  • successStatuses Response is success if response status is in this list (Default: [200,201, 202])
  • permanentErrors Response fails if response status is in this list (Default: [404, 415, 500, 501])

Properties

  • .support A boolean value indicator whether or not Flow.js is supported by the current browser.
  • .supportDirectory A boolean value, which indicates if browser supports directory uploads.
  • .opts A hash object of the configuration of the Flow.js instance.
  • .files An array of FlowFile file objects added by the user (see full docs for this object type below).

Methods

  • .assignBrowse(domNodes, isDirectory, singleFile, attributes) Assign a browse action to one or more DOM nodes.

    • domNodes array of dom nodes or a single node.
    • isDirectory Pass in true to allow directories to be selected (Chrome only, support can be checked with supportDirectory property).
    • singleFile To prevent multiple file uploads set this to true. Also look at config parameter singleFile.
    • attributes Pass object of keys and values to set custom attributes on input fields. For example, you can set accept attribute to image/*. This means that user will be able to select only images. Full list of attributes: https://www.w3.org/wiki/HTML/Elements/input/file

    Note: avoid using a and button tags as file upload buttons, use span instead.

  • .assignDrop(domNodes) Assign one or more DOM nodes as a drop target.

  • .unAssignDrop(domNodes) Unassign one or more DOM nodes as a drop target.

  • .on(event, callback) Listen for event from Flow.js (see below)

  • .off([event, [callback]]):

    • .off() All events are removed.
    • .off(event) Remove all callbacks of specific event.
    • .off(event, callback) Remove specific callback of event. callback should be a Function.
  • .upload() Start or resume uploading.

  • .pause() Pause uploading.

  • .resume() Resume uploading.

  • .cancel() Cancel upload of all FlowFile objects and remove them from the list.

  • .progress() Returns a float between 0 and 1 indicating the current upload progress of all files.

  • .isUploading() Returns a boolean indicating whether or not the instance is currently uploading anything.

  • .addFile(file) Add a HTML5 File object to the list of files.

  • .removeFile(file) Cancel upload of a specific FlowFile object on the list from the list.

  • .getFromUniqueIdentifier(uniqueIdentifier) Look up a FlowFile object by its unique identifier.

  • .getSize() Returns the total size of the upload in bytes.

  • .sizeUploaded() Returns the total size uploaded of all files in bytes.

  • .timeRemaining() Returns remaining time to upload all files in seconds. Accuracy is based on average speed. If speed is zero, time remaining will be equal to positive infinity Number.POSITIVE_INFINITY

Events

  • .fileSuccess(file, message, chunk) A specific file was completed. First argument file is instance of FlowFile, second argument message contains server response. Response is always a string. Third argument chunk is instance of FlowChunk. You can get response status by accessing xhr object chunk.xhr.status.
  • .fileProgress(file, chunk) Uploading progressed for a specific file.
  • .fileAdded(file, event) This event is used for file validation. To reject this file return false. This event is also called before file is added to upload queue, this means that calling flow.upload() function will not start current file upload. Optionally, you can use the browser event object from when the file was added.
  • .filesAdded(array, event) Same as fileAdded, but used for multiple file validation.
  • .filesSubmitted(array, event) Same as filesAdded, but happens after the file is added to upload queue. Can be used to start upload of currently added files.
  • .fileRemoved(file) The specific file was removed from the upload queue. Combined with filesSubmitted, can be used to notify UI to update its state to match the upload queue.
  • .fileRetry(file, chunk) Something went wrong during upload of a specific file, uploading is being retried.
  • .fileError(file, message, chunk) An error occurred during upload of a specific file.
  • .uploadStart() Upload has been started on the Flow object.
  • .complete() Uploading completed.
  • .progress() Uploading progress.
  • .error(message, file, chunk) An error, including fileError, occurred.
  • .catchAll(event, ...) Listen to all the events listed above with the same callback function.

FlowFile

FlowFile constructor can be accessed in Flow.FlowFile.

Properties

  • .flowObj A back-reference to the parent Flow object.
  • .file The correlating HTML5 File object.
  • .name The name of the file.
  • .relativePath The relative path to the file (defaults to file name if relative path doesn't exist)
  • .size Size in bytes of the file.
  • .uniqueIdentifier A unique identifier assigned to this file object. This value is included in uploads to the server for reference, but can also be used in CSS classes etc when building your upload UI.
  • .averageSpeed Average upload speed, bytes per second.
  • .currentSpeed Current upload speed, bytes per second.
  • .chunks An array of FlowChunk items. You shouldn't need to dig into these.
  • .paused Indicated if file is paused.
  • .error Indicated if file has encountered an error.

Methods

  • .progress(relative) Returns a float between 0 and 1 indicating the current upload progress of the file. If relative is true, the value is returned relative to all files in the Flow.js instance.
  • .pause() Pause uploading the file.
  • .resume() Resume uploading the file.
  • .cancel() Abort uploading the file and delete it from the list of files to upload.
  • .retry() Retry uploading the file.
  • .bootstrap() Rebuild the state of a FlowFile object, including reassigning chunks and XMLHttpRequest instances.
  • .isUploading() Returns a boolean indicating whether file chunks is uploading.
  • .isComplete() Returns a boolean indicating whether the file has completed uploading and received a server response.
  • .sizeUploaded() Returns size uploaded in bytes.
  • .timeRemaining() Returns remaining time to finish upload file in seconds. Accuracy is based on average speed. If speed is zero, time remaining will be equal to positive infinity Number.POSITIVE_INFINITY
  • .getExtension() Returns file extension in lowercase.
  • .getType() Returns file type.

Contribution

To ensure consistency throughout the source code, keep these rules in mind as you are working:

  • All features or bug fixes must be tested by one or more specs.

  • We follow the rules contained in Google's JavaScript Style Guide with an exception we wrap all code at 100 characters.

Installation Dependencies

  1. To clone your Github repository, run:
git clone [email protected]:<github username>/flow.js.git
  1. To go to the Flow.js directory, run:
cd flow.js
  1. To add node.js dependencies
npm install

Testing

Our unit and integration tests are written with Jasmine and executed with Karma. To run all of the tests on Chrome run:

grunt karma:watch

Or choose other browser

grunt karma:watch --browsers=Firefox,Chrome

Browsers should be comma separated and case sensitive.

To re-run tests just change any source or test file.

Automated tests is running after every commit at travis-ci.

Running test on sauceLabs

  1. Connect to sauce labs https://saucelabs.com/docs/connect
  2. grunt test --sauce-local=true --sauce-username=**** --sauce-access-key=***

other browsers can be used with --browsers flag, available browsers: sl_opera,sl_iphone,sl_safari,sl_ie10,sl_chrome,sl_firefox

Origin

Flow.js was inspired by and evolved from https://github.com/23/resumable.js. Library has been supplemented with tests and features, such as drag and drop for folders, upload speed, time remaining estimation, separate files pause, resume and more.

Comments
  • General discussion

    General discussion

    Hi,

    Well done with the library! Although it currently doesn't seem to be much difference between this and resumablejs, I prefer flow's code structure. Unfortunately it inherits the same big performance issue. The "testChunks" idea is nice, but it is useless in its current form. If let's say one have uploaded 5/10 chunks in a previous session and wishes to resume the transfer, wouldn't be more practical for Flow to send only ONE single GET requests to retrieve the size of what has been already uploaded to the server and continue from there, instead of testing all chunks from 1 to 10? There are a couple of more big problems, but let's start with this. I am willing to collaborate.

    Best regards,

    Vlad

    v3 
    opened by filerun 49
  • Asynchronous file bootstrap hooks, aka `async initFileFn`

    Asynchronous file bootstrap hooks, aka `async initFileFn`

    This is a follow-up (and proper implementation) of #296 (reverted in e867d54)

    This could be use to initialize a stream, a reader, fetch a remote resource, ... during the FlowFile initialization. asyncAddFile and asyncAddFiles are introduced which support this mechanism. These functions return promises of one (or multiple) FlowFile(s).

    Implement:

    • An AsyncFlowFile class extending a FlowFile is created, overriding the bootstrap part
    • In order to keep code-duplication low, a filterFileList generator yield files in way reusable by both async and non-async addFiles() versions.

    The possibly async' nature of initializing file hit back events firing (#319) in general and fileAddedin particular (#271) and the current confusión between hooks altering bootstraping and simple events.

    • fileAdded is now assumed an event. If we detect a return value, a warning is sent.
    • preFilterFile is introduced and allow filtering the raw file before bootstrap()
    • postFilterFile is introduced and allow filtering the FlowFile after a (possibly async) bootstrap()
    • filesAdded is preserved

    About parameters:

    • initFileFn is only used during bootstrap
    • If such a helper exists, it's tightly related to addFile* functions. As such, it was deemed adequate to provide it as a parameter to *addFile*() (but opts.initFileFn is still supported)
    opened by drzraf 16
  • $_FILES missing size and type after flow.js upload

    $_FILES missing size and type after flow.js upload

    Hello,

    I'm trying to get flow.js ready. This is how I've set up flow.js:

    $(document).ready(function(){
    
                var flow = new Flow({
                    target: '{$uploadUrl}',
                    singleFile: true,
                    maxChunkRetries: 0,
                    testChunks: false
                });
    
                flow.assignBrowse($('#{$addButtonId}').get());
    
                flow.on('fileAdded', function(file, event){
    
                    console.log(file, event);
                    console.log('added');
                });
                flow.on('fileSuccess', function(file,message){
                    console.log(file,message);
                    console.log('succes');
                });
                flow.on('fileError', function(file, message){
                    console.log(file, message);
                    console.log('error');
                });
                flow.on('filesSubmitted', function (file) {
                    console.log(file);
                    file[0].flowObj.upload();
                });
     });
    

    Everything works fine, except that the PHP script at $uploadUrl does only receive the following in $_FILES (var_dump()'d at the first line, so nothing can interfere):

    array (
      'file' => 
      array (
        'name' => 'select-css.txt,
        'type' => '0',
        'tmp_name' => '/tmp/php99aZVY',
        'error' => 0,
        'size' => 0,
      ),
    )
    

    So, $_FILES['size'] and $_FILES['type'] is missing, which makes it an invalid upload. I'm using flowjs/flow-php-server on the server side. Note that $_FILES['error']is 0, so this shouldn't be an error due to php upload_max_size etc

    The request send to the server has the following payload (using Chrome):

    ------WebKitFormBoundaryJNrM1tKMEhvD5dag
    Content-Disposition: form-data; name="flowChunkNumber"
    
    1
    ------WebKitFormBoundaryJNrM1tKMEhvD5dag
    Content-Disposition: form-data; name="flowChunkSize"
    
    2097152
    ------WebKitFormBoundaryJNrM1tKMEhvD5dag
    Content-Disposition: form-data; name="flowCurrentChunkSize"
    
    1561
    ------WebKitFormBoundaryJNrM1tKMEhvD5dag
    Content-Disposition: form-data; name="flowTotalSize"
    
    1561
    ------WebKitFormBoundaryJNrM1tKMEhvD5dag
    Content-Disposition: form-data; name="flowIdentifier"
    
    1561-select-csstxt
    ------WebKitFormBoundaryJNrM1tKMEhvD5dag
    Content-Disposition: form-data; name="flowFilename"
    
    select-css.txt
    ------WebKitFormBoundaryJNrM1tKMEhvD5dag
    Content-Disposition: form-data; name="flowRelativePath"
    
    select-css.txt
    ------WebKitFormBoundaryJNrM1tKMEhvD5dag
    Content-Disposition: form-data; name="flowTotalChunks"
    
    1
    ------WebKitFormBoundaryJNrM1tKMEhvD5dag
    Content-Disposition: form-data; name="file"; filename="select-css.txt"
    Content-Type: 0
    
    
    ------WebKitFormBoundaryJNrM1tKMEhvD5dag--
    

    Another jquery file upload librariy works well and the standard POST upload, too. What am I doing wrong that prevents flow.js from sending the correct size and type?

    opened by arkuuu 16
  • Publish the package in the npm registry

    Publish the package in the npm registry

    I wan't to use this package with webpack, but there is no published version of the package in npm.

    There is another problem: The npm package name flow.js is already registered.

    For publishing in npm registry two steps are necessary:

    • Change the name in package.json to any unused name. Maybe flowjs?
    • Publish it to the registry. Should be done by some mantainer, if not I could.

    Any better idea?

    opened by Undergrounder 15
  • Ability to use ES6: rollup+babel transpilation

    Ability to use ES6: rollup+babel transpilation

    This change gives the opportunity to use ES6 for src/flow.js

    • karma.conf.js : Test the transpiled bundle instead of ES6 code.
    • babel: use bable-env + browserlist to transpile for a wider range of browsers.
    • For that purpose, switch to rollup with way handier and more modern than browserify.
    • In order to keep the toolchain backward-compatible (and reduce the PR surface), use grunt:exec to wrap rollup execution.

    Also update to karma-coverage v2 needed for async support as discussed and anticipated in https://github.com/flowjs/flow.js/pull/304.

    opened by drzraf 12
  • Future of this library?

    Future of this library?

    Hello there

    Is this really the official, next version of https://github.com/23/resumable.js ?

    I realise it has some flaws and I wonder if I really should use yours instead. Which one is better maintained and will be?

    Lemme know, thanks!

    opened by binarykitchen 12
  • strip console.* in dist/flow.min.js

    strip console.* in dist/flow.min.js

    Addressing a comment from #304

    I suggest either:

    • to only drop console.* from one of the bundle (.js or .min.js) so that the other can be used during test (and still show the output)
    • either do it based on an environment variable.

    Keeping console.log accelerates development and it sounds better to leave to the toolchain the job of striping them when needed.

    opened by drzraf 11
  • Get http code with fileError

    Get http code with fileError

    Is there a way to retrieve http code on error ?

    I use flowjs with Angular(4), i need to know when my token has expired (http code: 401). In my Angular services i have an auto refresh for this case, but flowjs requests working in parallel (because no Angular module or integration at this time). For the moment i grep on error message but it is a low check, an error code is cleaner.

    opened by johaven 10
  • Misfire event 'complete' when resuming multiple files upload with first file had been completed

    Misfire event 'complete' when resuming multiple files upload with first file had been completed

    When pausing and then resuming multiple files upload with the first file had been completed, flow will misfire event 'complete' in method flow.upload().

    The reason is because flow.resume() resumes each file without checking if it has been completed.

    Suggesting fix: change flow.resume() from:

    each(this.files, function (file) { file.resume(); });

    to

    each(this.files, function (file) { if (! file.isComplete()) file.resume(); });

    opened by koolphp 9
  • flow::fileAdded event invoke twice in IE11 and not invoke in IE10 with special scenario

    flow::fileAdded event invoke twice in IE11 and not invoke in IE10 with special scenario

    Defect 1 : IE11 select one file to upload , the addFile method and flow::fileAdded event invoke twice. Defect 2 : IE10 if user select one file, remove from upload queue,then select this file again, fileAdded event will not fire. Solution :

     assignBrowse: function (domNodes, isDirectory, singleFile, attributes) {
                if (typeof domNodes.length === 'undefined') {
                    domNodes = [domNodes];
                }
                each(domNodes, function (domNode) {
                    function onSelectionChange (e) {
                        if (e.target.value) {
                            $.addFiles(e.target.files, e);
                            e.target.value = '';
                        }
                    }
    
                    var $ = this;
                    var input;
                    if (domNode.tagName === 'INPUT' && domNode.type === 'file') {
                        input = domNode;
                    } else {
                        input = document.createElement('input');
                        input.setAttribute('type', 'file');
                        // display:none - not working in opera 12
                        extend(input.style, {
                            visibility: 'hidden',
                            position: 'absolute'
                        });
                        // for opera 12 browser, input must be assigned to a document
                        domNode.appendChild(input);
                        // https://developer.mozilla.org/en/using_files_from_web_applications)
                        // event listener is executed two times
                        // first one - original mouse click event
                        // second - input.click(), input is inside domNode
                        domNode.addEventListener('click', function () {
                            //http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery/13351234#13351234
                            // reset input node to avoid select same file change event not fire issue.
                            if (input.value) {
                                domNode.innerHTML = domNode.innerHTML; // reset input file
                                input = domNode.children[0];
                                input.addEventListener('change', onSelectionChange, false);
                            }
                            input.click();
                        }, false);
                    }
                    if (!this.opts.singleFile && !singleFile) {
                        input.setAttribute('multiple', 'multiple');
                    }
                    if (isDirectory) {
                        input.setAttribute('webkitdirectory', 'webkitdirectory');
                    }
                    each(attributes, function (value, key) {
                        input.setAttribute(key, value);
                    });
                    // When new files are added, simply append them to the overall list
    
                    input.addEventListener('change', onSelectionChange, false);
                }, this);
            },
    
    opened by kalavt 9
  • First large file upload crashes Chrome

    First large file upload crashes Chrome

    Strange behaviour. If the first upload in a Chrome tab is "large" (perhaps requiring more than one chunk), the tab will crash. However, if you first upload a smaller file, then the same large file, it works fine. Interestingly, when I perform the same steps in Safari, it doesn't crash. However, it does seem to temporarily hang my progress bar, leading me to think that Chrome just has a shorter timeout before crashing. What is particular about the first upload that might cause this slowdown/crash?

    opened by mattbodman 9
  • flowTotalSize is 0  when uploading folder with longer path

    flowTotalSize is 0 when uploading folder with longer path

    Steps to produce

    1. Create folder inside folder and make long path . (absolute path with a total number of more than 256 characters)
    2. Put valid files inside folder
    3. Upload via flow js using folder upload
    4. Observe request headers , flowCurrentChunkSize ,flowTotalSize , both will be set as 0.
    opened by arifmahammad 0
  • Typecasting Object assignment within Array.forEach

    Typecasting Object assignment within Array.forEach

    Hi,

    This might be a silly question but...

    I need to reset some Object values and I decided to use a forEach loop. This Object values are defined as it follows:

    image

    Basically, I've declared this Object type. It's important the Object contains at least 2 attributes with different types. For example, a number and a string:

    type FooType = {|
      a: number,
      b: string
    |}
    

    And I have written an Object of the same type that will be used to set/reset the initial values in another one of the same type.

    const INITIAL_FOO: FooType = {
      a: 0,
      b: ''
    }
    const foo: FooType = {
      a: 1,
      b: 'qwerty'
    }
    

    Therefore, when I use the Array.forEach for an assignment I get the following flow error:

    Object.keys(foo).forEach((key) => {
      foo[key] = (INITIAL_FOO[key]: any); // This works
    })
    Object.keys(foo).forEach((key) => {
      foo[key] = INITIAL_FOO[key];        // This fails
    })
    
    
    18:   foo[key] = INITIAL_FOO[key];        // This fails
                     ^ Cannot assign `INITIAL_FOO[key]` to `foo[key]` because number [1] is incompatible with string [2]. [incompatible-type]
    References:
    3:   a: number,
            ^ [1]
    4:   b: string        ^ [2]
    18:   foo[key] = INITIAL_FOO[key];        // This fails
                     ^ Cannot assign `INITIAL_FOO[key]` to `foo[key]` because string [1] is incompatible with number [2]. [incompatible-type]
    References:
    4:   b: string        ^ [1]
    3:   a: number,
            ^ [2]
    

    I guess that Flow is not able to detect that the key used to read from INITIAL_FOO and the key used to write in foo are the same on every loop.

    Is there any way to fix this and keep the forEach loop?

    Here is a link to test this example: https://flow.org/try

    Thanks,

    opened by SergioRevueltas 0
  • Upload to azure blob crash on large files

    Upload to azure blob crash on large files

    Hello I want to upload a file using chunks to azure blob storage , the multiple c hunks crash and the upload is not compeleted any help

    
    submitFlow: function () { 
    				$scope.blockIds = [];
    				$scope.fileTargetUrl =	MyoFileUpload.getUploadFileURL($scope.fileManager.getFlowFile())
    				$scope.flowObj.flow.upload();
    			}, 
    
    preprocess: function (chunk) {
    			
    				const value = create_UUID();
    				const blockId = btoa(value);
    				$scope.blockIds.push(blockId);
    				chunk.flowObj.opts.target =
    				$scope.fileTargetUrl  +
    				  `&comp=block&blockid=${blockId}`;
    				  var flowFile = chunk.fileObj;
    				  var originalpxr = chunk.prepareXhrRequest;
    				  chunk.prepareXhrRequest = function (method, isTest, paramsMethod, blob) {
    					  var data = originalpxr.apply(this, arguments);
    					  data = this.fileObj.file;
    					  this.flowObj.opts.query = {};
    					  return data;}
    				chunk.preprocessFinished();
    			  },
    uploadCompleted :function()
    			  { 
                              if($scope.fileManager.isCompleted)
    				{  
                                        MyoFileUpload.commitChunksList($scope.blockIds,$scope.fileTargetUrl );
    				}
    			  },
    
    commitChunksList(blockIds, url)
            { 
                var uri = url + '&comp=blocklist';
                console.log(uri);
                var requestBody = '<?xml version="1.0" encoding="utf-8"?><BlockList>';
                for (var i = 0; i < blockIds.length; i++) {
                    requestBody += '<Latest>' + blockIds[i] + '</Latest>';
                }
                requestBody += '</BlockList>';
                console.log(requestBody);
                $.ajax({
                    url: uri,
                    type: "PUT",
                    data: requestBody,
                  
                    success: function (data, status) {
                        console.log(data);
                        console.log(status);
                    },
                    error: function (xhr, desc, err) {
                        console.log(desc);
                        console.log(err);
                    }
                });
     
            },
     
    
    opened by SanaaAfifi 0
  • Can't upload empty file when using asyncReadFileFn hook [v3 regression]

    Can't upload empty file when using asyncReadFileFn hook [v3 regression]

    Hi,

    I'm using V3 branch since multiple months and it works well but i've discoved this small regression. I'm unable to send empty files when using asyncReadFileFn hook.

    Investigating, it seems to come from there: https://github.com/flowjs/flow.js/blob/5591263e71426fb811f9495457380f81798a09af/src/FlowChunk.js#L341

    From what i've seen convert to this fix it: if (data && (data.size > 0 || this.fileObj.size === 0)) {

    But i would like to have a feedback from you @drzraf before making an MR.

    opened by bertrandg 6
  • Bump npm dependencies

    Bump npm dependencies

    @AidasK : Would you please review this pull request and merge?

    Tests seems to be working correctly: https://app.travis-ci.com/github/flowjs/flow.js/builds/245693965

    Thank you!

    opened by evilaliv3 3
  • Filter addFiles between hooks

    Filter addFiles between hooks

    • Makes addFiles call files-added hook with a file list filtered by every individual file-added hook
    • Adds a test to make sure that files-added hook won't receive files that file-added has deleted
    • Cleanup: removed the intermediary state objects and array, reducing the times the file list is looped through from 3 to 2
    • Code styling: unify variable names (flowfiles -> flowFiles, e -> flowFile)
    opened by ilessiivi 0
Releases(v2.14.1)
Owner
HTML5 File upload
HTML5 File upload
Moxiecode 5.6k Jan 1, 2023
Multiple file upload plugin with image previews, drag and drop, progress bars. S3 and Azure support, image scaling, form support, chunking, resume, pause, and tons of other features.

Fine Uploader is no longer maintained and the project has been effectively shut down. For more info, see https://github.com/FineUploader/fine-uploader

Fine Uploader 8.2k Jan 2, 2023
🌊 A flexible and fun JavaScript file upload library

A JavaScript library that can upload anything you throw at it, optimizes images for faster uploads, and offers a great, accessible, silky smooth user

pqina 13.2k Jan 3, 2023
FileAPI — a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.

FileAPI A set of JavaScript tools for working with files. Get started Download the files from the dist directory, and then: <div> <!-- "js-fileapi-

Free and open source software developed at Mail.Ru 3.6k Jan 3, 2023
runk is a simple file and folder sharer.

runk It is a simple file and folder sharer. It uses hyperswarm for sharing over network. Installation: Prerequisite: Node.js To mount, configured fuse

Amansinh Parmar 8 Mar 11, 2022
Dropzone is an easy to use drag'n'drop library. It supports image previews and shows nice progress bars.

Dropzone is a JavaScript library that turns any HTML element into a dropzone. This means that a user can drag and drop a file onto it, and Dropzone wi

Dropzone 17k Dec 30, 2022
A simple React App that plays Public Domain TV shows and integrates with Twitch Chat for the controls.

Public Domain Television for Twitch This application plays movies from Public Domain Movies The current version is only used to play Cartoons, but can

Ravavyr 8 Mar 29, 2022
🔬 Writing reliable & fault-tolerant microservices in Node.js

A Node.js microservices toolkit for the NATS messaging system Run on repl.it Node: v6+ Documentation: https://hemerajs.github.io/hemera/ Lead Maintain

HemeraJs 800 Dec 14, 2022
⚡️The Fullstack React Framework — built on Next.js

The Fullstack React Framework "Zero-API" Data Layer — Built on Next.js — Inspired by Ruby on Rails Read the Documentation “Zero-API” data layer lets y

⚡️Blitz 12.5k Jan 4, 2023
A front end GUI for interacting with the Stable Horde / Stable Diffusion distributed cluster

ArtBot for Stable Diffusion See it in action: https://tinybots.net/artbot ArtBot is a front-end GUI for generating images and photos with Stable Diffu

Dave Schumaker 39 Jan 2, 2023
🤗 A CLI for running Stable Diffusion locally via a REST API on an M1/M2 MacBook

Stable Diffusion REST API A CLI for running Stable Diffusion locally via a REST API on an M1/M2 MacBook Pre-requisites An M1/M2 MacBook Homebrew Pytho

Yuan Qing Lim 74 Dec 26, 2022
DOMPurify - a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. DOMPurify works with a secure default, but offers a lot of configurability and hooks. Demo:

DOMPurify DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. It's also very simple to use and get started with

Cure53 10.2k Jan 7, 2023
Moxiecode 5.6k Jan 1, 2023
Next-multipart - Easy & Simple File Uploads for Next.js

Next-Multipart Next-multipart is a small utility library to ease the process of file uploads with Next.js. It uses formidable under the hood, but with

Tim Raderschad 10 Nov 11, 2022
Script written in JavaScript (Node) that uploads CGM readings from LibreLink Up to Nightscout

Nightscout LibreLink Up Uploader/Sidecar Simple Script written in JavaScript (Node) that uploads CGM readings from LibreLink Up to Nightscout. The upl

Timo Schlüter 87 Jan 7, 2023
Responsive, interactive and more accessible HTML5 canvas elements. Scrawl-canvas is a JavaScript library designed to make using the HTML5 canvas element a bit easier, and a bit more fun!

Scrawl-canvas Library Version: 8.5.2 - 11 Mar 2021 Scrawl-canvas website: scrawl-v8.rikweb.org.uk. Do you want to contribute? I've been developing thi

Rik Roots 227 Dec 31, 2022
Plugin to backup & restore your strapi installation (database + uploads) from admin panel.

Strapi Backup & Restore plugin Add backup and restore features directly inside your strapi admin panel. Supported databases: mysql sqlite postgre mong

Hugues BUREAU 41 Dec 19, 2022
Automatically uploads a list of patrons to VRChat everytime a patron joins or leaves, without reuploading the world

Automatically uploads a list of patrons to VRChat everytime a patron joins or leaves, without reuploading the world. For use with Miner28/AvatarImageReader

Paul 10 Nov 13, 2022