{"id":19746817,"url":"https://github.com/massimo-cassandro/js-file-uploader","last_synced_at":"2025-04-30T08:31:51.261Z","repository":{"id":35064697,"uuid":"171548736","full_name":"massimo-cassandro/js-file-uploader","owner":"massimo-cassandro","description":"HTML5 Async File Uploader","archived":false,"fork":false,"pushed_at":"2024-09-26T08:09:06.000Z","size":4802,"stargazers_count":2,"open_issues_count":16,"forks_count":3,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-11-07T23:41:55.919Z","etag":null,"topics":["ajax","forms","interaction-design","javascript","upload-file","user-experience","user-interface","ux"],"latest_commit_sha":null,"homepage":"https://massimo-cassandro.github.io/js-file-uploader/demo","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/massimo-cassandro.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.txt","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-19T20:58:28.000Z","updated_at":"2024-09-26T08:09:03.000Z","dependencies_parsed_at":"2024-06-16T21:32:36.852Z","dependency_job_id":"b5b856ab-11db-4dea-88f6-8cc8cdd34662","html_url":"https://github.com/massimo-cassandro/js-file-uploader","commit_stats":{"total_commits":213,"total_committers":8,"mean_commits":26.625,"dds":"0.46478873239436624","last_synced_commit":"f172217c41f56ef7997756518764d7b88716001a"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massimo-cassandro%2Fjs-file-uploader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massimo-cassandro%2Fjs-file-uploader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massimo-cassandro%2Fjs-file-uploader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/massimo-cassandro%2Fjs-file-uploader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/massimo-cassandro","download_url":"https://codeload.github.com/massimo-cassandro/js-file-uploader/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224202778,"owners_count":17272807,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ajax","forms","interaction-design","javascript","upload-file","user-experience","user-interface","ux"],"created_at":"2024-11-12T02:15:58.839Z","updated_at":"2024-11-12T02:15:59.365Z","avatar_url":"https://github.com/massimo-cassandro.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FileUploader\n\n**js-file-uploader: HTML5 + Javascript asyncronous file upload.**  \n*v. 3 - Massimo Cassandro - (c) 2017/2021*\n\n[demo](https://massimo-cassandro.github.io/js-file-uploader/demo/)\n\nJS-File-Uploader is a small javascript utility (less than 8kb minified and gzipped) that simplifies uploading files to HTML pages.\n\nUploads are performed asynchronously via an Ajax call to a server-side script that must register the file and return a JSON string.\n\nAlthough the default settings are based on Bootstrap 4, FileUploader is entirely and easily configurable from scratch and can be adapted to any layout.\n\nThe [demo](https://massimo-cassandro.github.io/js-file-uploader/demo/) folder contains many examples of FileUploader using.\n\nWorks with all modern browser (tested thanks to [Browserstack Open Source program](https://www.browserstack.com/open-source)).\n\n## Features\n\n* Provide the user with a better interface and feedback than the standard input-file element: it can instantly show a preview of the uploaded file (if it is image) and show some information like name, size etc.\n* Provide an easy way to add constraints to file format, aspect ratio, size and weight\n* Perform multiple uploads in file-by-file way, thus avoiding any server-side limitations on upload size\n\n![Single image uploader](readme-imgs/single-image-screenshot.jpg) \n\n* Although the default settings are based on Bootstrap 4, JS-File-Uploader is entirely and easily configurable from scratch and can be adapted to any layout.\n* All string messages can be customized using the desired language (the default language is Italian and an English translation is included in the distribution).\n\nThe [demo](https://massimo-cassandro.github.io/js-file-uploader/demo/) folder contains many examples of FileUploader using.\n\n\n## Browser compatibility\n\nJS-File-Uploader needs a modern browser and is not compatible with Internet Explorer.\n\nAnyway, providing a fallback `input[type=\"file\"]` field (recommended), JS-File-Uploader silently degrade to the input element. You just have to provide that the server-side processing includes this possibility.\n\nJS-File-Uploader is tested with many browsers and mobile devices (thanks to [Browserstack Open Source program](https://www.browserstack.com/open-source)).\n\n\n## Installation and startup\n\nJS-File-Uploader can be installed using [npm](https://www.npmjs.com/package/@massimo-cassandro/js-file-uploader):\n\n```bash\nnpm i @massimo-cassandro/js-file-uploader\n```\n\nYou can add JS-File-Uploader importing the bundled ES module version contained in the `dist` folder, or the original source from `src`:\n\n```js\n// bundled ESM version\nimport FileUploader from `@massimo-cassandro/js-fileuploader/dist/FileUploader.esm.min.js`;\n```\n\n```js\n// source version\nimport FileUploader from `@massimo-cassandro/js-fileuploader/src/file_uploader`;\n```\n\nAll the demo pages load JS-File-Uploader from `src`.\n\n\nYou can also use the UMD version directly in your browser:\n\n```html\n\u003cscript src=\"path/to/FileUploader.umd.min.js\"\u003e\u003c/script\u003e\n\n\u003c!-- optional language --\u003e\n\u003cscript src=\"path/to/en.umd.min.js\"\u003e\u003c/script\u003e\n```\n\n`FileUploader.umd.min.js` exposes the `FileUploader` global variable, and `en.umd.min.js` exposes `fupl_strings_en`. Take a look to the [UMD demo](https://massimo-cassandro.github.io/js-file-uploader/demo/umd-version-demo.html) for a detailed example.\n\n### CSS\n\nYou also need to add some css to make JS-File-Uploader work.\n\nThe best and easiest way is to use the SCSS files contained in the `scss` directory. However there is a compiled ` .css` file into `dist`.\n\nYou just need to import the `fileUploader.scss` file into your project. To customize colors and other properties, change the values of the variables listed in `_fupl-default-variables.scss` before importing:\n\n```scss\n$fupl-outline-color: #ddd;\n$fupl-outline-color-dragover: #e4d70d;\n$fupl-background-color: #fbfbfb;\n// ...\n\nimport 'scss/fileUploader.scss';\n```\n\n### Starting JS-File-Uploader\n\nTo start FileUploader you must first add it to your pages as explained before, and then instantiate it:\n\n```js\nFileUploader({\n    selector    : [string] // selector of fileuploader elements (default `.file-uploader2`)\n    options     : [object] // custom options\n    css         : [string] // css url\n    local_strs  : [object] // localized strings\n})\n```\n\nwhere:\n\n* `selector` is a string to use as a selector for FileUploader elements. It can be a `class`, an `id` or any other valid selector. FileUploader will be automatically activated on these items. The default is `.file-uploader2`\n* `options` is an object of various parameters to modify the behaviors of FileUploader. This object contains the only required configuration option: `uploader_url`, the server-side scripting URL needed to save remote files. Read the [FileUploader Options] (options) chapter for details on all parameters.\n* `css` if the optional url for the css file used by FileUploader. Since it can be joined with your project css file, this parameter can be `null`.\n* `local_strs` is an object that contains localized strings for FileUploader interface. Read the **Languages** paragraph in this page for more info.\n\nTherefore, a really minimal FileUploader setup could be:\n\n```html\n\u003cdiv class=\"file-uploader2\"\u003e\u003c/div\u003e\n\n\u003cscript type=\"module\"\u003e\n  import FileUploader from '@massimo-cassandro/js-fileuploader/dist/FileUploader.esm.min.js';\n  FileUploader({\n    options: {\n      uploader_url: '/path/to/server-side-script'\n    }\n  })\n\u003c/script\u003e\n```\n\nHowever, it is very likely that you will need to configure additional parameters, add a fallback for older browsers or improve accessibility. For a more complete explanation of FileUploader configuration, read the [Setup](setup) chapter.\n\n### Languages\n\nJS-File-Uploader main language is Italian. An english translation is provided (but you may need to make some adjustments...).\n\nTo add other languages, you need to translate ʻen.js` or ʻit.js` (in the `src/i18n` directory) and use the new file when starting JS-File-Uploader:\n\n```js\nimport FileUploader from `@massimo-cassandro/js-fileuploader/src/file_uploader`;\n\n// exposes the var `my_lang`\nimport fupl_strings_en from 'path/to/new_language.js';\n\nFileUploader({\n  options: {\n    // ... options ...\n  },\n  local_strs: my_lang\n});\n```\n\nYou can also send a pull request for you translation file, to have it included in future JS-File-Uploader distributions.\n\n\n## Server-Side scripting\n\n\nFileUploader requires a server-side script to manage file uploading.\n\nThe goal of FileUploader is to allow asynchronous uploading of files, saving them definitively on server only after the form containing the input file has been submitted. The script must place the file in a temporary directory (eg `tmp`), giving it a temporary name.\n\nAfter form submit, uploaded files have to be be moved to their final destination: this way any unsubmitted form will not leave any *orphaned* file, since the files left in the `tmp` directory should be periodically deleted.\n\n\nWhen a file is uploaded, FileUploader receives from the server side script, the information necessary to complete the registration, inserts it in a series of hidden inputs, and returns it to the server when the form is submitted.\n\nFor each file selected, FileUploader send to server-side script a *POST* call with file data. PHP `$_FILES` variable, for example, returns to the script something like this:\n\n```php\nArray\n(\n    [file] =\u003e Array\n        (\n            [name] =\u003e myfile.jpg\n            [type] =\u003e image/jpeg\n            [tmp_name] =\u003e /tmp/php/phpGu39M5\n            [error] =\u003e 0\n            [size] =\u003e 8772\n        )\n)\n```\nThe script must process the request (save the file in `tmp` directory), and return a json formatted as follows:\n\n\n```json\n{\n  \"tmp_file\": \"path/to/tmp/file\",\n  \"error\": null\n}\n```\n\nwhere:\n\n* `tmp_file` is the path to the temporary file registered on the server\n* `error` is` null` on success, or a string of the error message produced by the server.\n\nThen FileUploader will build a hidden field for each of these parameters:\n\n* `tmp_file`: name of temporary file (as returned by the json response)\n* `file_name`: name of the original file (web normalized)\n* `size`: file size (bytes)\n* `type`: file mimetype\n\nIn case of images, the `width` and` height` values ​​of the image itself will also be present.\n\nAll values will be used to create some *hidden* fields whose `name` attribute will consist of:\n\n* the value of the `varname` parameter\n* an unique id corresponding to the file\n* the variable name\n\nExample (with `varname='custom_file'` and unique id equal to `__unique_id__`):\n\n```html\n\u003cinput type=\"hidden\" name=\"custom_file[__unique_id__][tmp_file]\" value=\"...\"\u003e\n\u003cinput type=\"hidden\" name=\"custom_file[__unique_id__][file_name]\" value=\"...\"\u003e\n[...]\n```\n\nA demo including a server side sample script can be found in the repository at `demo/php_sample`\n\n\n## Detailed setup\n\n### Starting uploader\n\nThe minimal needed markup is \n\n```html\n\u003cdiv data-file-uploader\u003e\u003c/div\u003e\n```\n\nAnyway, to ensure accessibility and graceful degrations is strongly recommended to add a fallback input field:\n\n```html\n\u003cdiv data-file-uploader\u003e\n    \u003cinput type=\"file\" name=\"fallback-field\"\u003e\n\u003c/div\u003e\n```\n\nWhen FileUploader is started, the internal field is replaced with a generated one.\nBut if it fails, by adding the inner field you can ensure the basic functionality of your form.\n\n### Parameters setting\n\nFileUploader configuration is based on parameters defined in `src/_default_options.js`\n\nThe parameters can be overridden according to this cascading sequence:\n\n* Values of `_default_options.js` file are the default ones\n* Parameters assigned in the `FileUploader()` obj argument override the default ones, and are valid for all the FileUploader elements involved\n* Parameters assigned to each FileUploader instance, using `data-*` attributes, prevail and override the previous ones: in this way it is possible to have different behaviors also on the same page.\n\nFinally, if an `input [type=\"file\"]` field is present inside the FileUploader element, any `accept`,` required`, `multiple` or` disabled` attributes are taken into account in the configuration .\n\nFor example, you can set a FileUploader as *required* either by setting the `data-required=\"true\"` attribute of the FileUploader element, or by using the` required` attribute of the file field.\n\nData attributes can be set as single items (e.g. `data-disabled=\"true\"`) or as a json object to be assigned to the `data-file-uploader` attribute:\n\n```html\n\u003cdiv data-file-uploader='{\"disabled\": true, \"multiple\": true}'\u003e\n```\n\n\u003eNB: if the `required`,` multiple` or `disabled` parameters are set to `true` in the FileUploader instance, it is not possible to set them to `false` via the input field attributes.\n\nSee `_default_options.js` for a complete list of all parameters.\n\n\n### Deleting a pre-registered file\n\nWhen a pre-registered file is removed from FileUploader, a hidden field is generated.\n\nIt contains the id of the removed file as `value` and the `delete_varname` parameter as `name`.\n\nYou must provide the necessary server side script to definitively remove the file from the server.\n\n```html\n\u003cinput type=\"hidden\" name=\"delete_file_var[]\" value=\"123\"\u003e\n```\n\n### Customization\n\nFileUploader configuration parameter allow you to radically change the generated layout.\n\nTo perform a complete customization of the layout, you can modify both the css and much of the markup.\nfurthermore, some callbacks can be set to perform additional operations.\n\nWhen a FileUploader  is generated, the `fupl` class is added to the original element (black bordered in the following diagram), and some additional markup is then generated inside and outside it. The internal one (blue bordered) is completely configurable by modifying the templates parameters.\n\n![Schema markup](readme-imgs/markup_schema.png)\n\n\u003e Take care to preserve elements with `fupl-*` classes, that are requested by FileUploader\n\n\n#### Callbacks\n\nIf specific behaviors are required, you can define some callback functions that will be invoked when certain events occur:\n\n* `init_callback` (default null): called after the initialization of each FileUploader element. The argument of this function is an object containing all the options of the instance\n\n* `upload_start_callback` (default null): function called whenever a file is sent to the server. The function is invoked by passing an object containing:\n    * `item`: object. It contains:\n        - `id`: unique ID of the item\n        - `file`: current * filelist * object\n        - `width` and `height`: null or dimensions in pixels of the image\n        - `tmp_file`: temporary file name assigned by the server side script\n    * `img_preview`: image thumbnail as a Base64 string\n    (null if it is of other types)\n    * `options`: options of current FileUploader instance\n\n* `upload_complete_callback` (default null): function called whenever a file is loaded. The function is invoked by passing an object containing:\n     * `item`: object. It contains:\n        - `id`: unique ID of the item\n        - `file`: current * filelist * object\n        - `width` and `height`: null or dimensions in pixels of the image\n        - `tmp_file`: temporary file name assigned by the server side script\n    * `server_error`: null, if the upload was completed successfully, or string with the returned error message\n    * `options`: options of current FileUploader instance\n\n* `alternative_loading_func` (default null): Not a real callback, but an alternative function to display the upload progress. If present, it replaces the standard one.\nIt is invoked with two parameters:\n    - `progress_event`: progress upload event\n    - `options`: options of current FileUploader instance\n\n\n### Fancybox integration\n\nFileUploader can be integrated with [Fancybox (v. 3)](https://www.fancyapps.com/fancybox/3/), simply setting\nthe `fancybox` option to `true`.\n\nFancybox application files are not loaded by FileUploader and have to be present in the HTML page before FileUploader loads.\n\nFancybox is applied only to previously registered images.\n\n\n## Recipes\n\n\n### Checking for completed loading\n\nAs soon as an item is added to the uploader, an Ajax request is sent to the server for file registration. When the operation is completed, the server returns a json with the data of the recorded file, as indicated in the previous points.\n\nFrom the moment the request is sent and until the server responds, the user can still submit the form, but in this case all the hidden elements related to the uploading file that will not be will not be present, therefore they will noit be registered\n\nTo avoid this problem, you can enable the `disable_submit` option which disables the *Submit * button of form until the server has sent its response.\n\nHowever, this option is not sufficient to ensure that problems of this type are avoided (in some cases, the user could submit with the Enter key), and it is also possible that other settings re-enable the button regardless of the upload outcome.\n\nThe safest solution is therefore to block the submit if there are elements with the `fupl-is-uploading` class, class assigned to each new element added to the uploader and deleted upon completion of loading:\n\n```javascript\nlet myForm = document.getElementById('myForm');\nmyForm.addEventListener('submit', () =\u003e {\n    if(myForm.querySelectorAll('.fupl-is-uploading').length) {\n        alert('Loading not completed');\n        return false;\n    }\n});\n```\n\nIf FileUploader is used in multiple pages, it is possible to set a centralized control on all form elements:\n\n```javascript\ndocument.querySelectorAll('form').forEach( this_form =\u003e {\n    this_form.addEventListener('submit', () =\u003e {\n        if(this_form.querySelectorAll('.fupl-is-uploading').length) {\n            alert('Wait for the image upload to complete!');\n            return false;\n        }\n    });\n});\n```\n\nThe module `src-utilities/check_uncompleted_uploads.js` is already ready for this purpose. Check the [uncompleted upload demo page](https://massimo-cassandro.github.io/js-file-uploader/demo/uncompleted-upload.html)\n\nHowever, implementing a server-side control too is certainly a good idea.\n\n\n### Required fields checking\n\nSince a file can be loaded via *Drag \u0026 Drop*, it is not possible to use the native `required` to check for  mandatory files.\n\nHowever, this check can be performed using the `data` attributes added dynamically to the` .fupl-wrapper` element: `data-required=\"true\"` and `data-has-values=\"true|false\"`.\n\nTherefore, to verify the required content of the `# my-uploader` element, it is very simple:\n\n```javascript\ndocument.getElementById('my-uploader')\n    .closest('.fupl-wrapper:not([disabled])[data-required=\"true\"][data-has-values=\"true\"]') !== null\n```\n\nOr, to check the entire form:\n\n```javascript\ndocument.querySelectorAll('.fupl-wrapper:not([disabled])[data-required=\"true\"][data-has-values=\"false\"]').length === 0\n```\n\nYou can also import the ready-to-use `scr-utilities/check_required_uploader.js` script in your project. Take a look at the [required uploader demo page](https://massimo-cassandro.github.io/js-file-uploader/demo/required.html)\n\n\n## About the demo\n\nThe examples in the [demo](https://massimo-cassandro.github.io/js-file-uploader/demo/) folder load FileUploader directly from the ES6 modules in the  \u003ccode\u003esrc\u003c/code\u003e folder, but you can easily use one of the UMD version present in the “dist” folder (see the **UMD version demo**) or the compiled all-in-one ES6 module version.\n\nThey also do not use a server-side engine (so the form tag is not present, except in some cases) and therefore the server response is simulated thru a static json file (\u003ccode\u003edemo/demo-assets/server-side-demo-response.json\u003c/code\u003e). However, there is a simple php example of server-side application (in \u003ccode\u003e/demo/php_sample\u003c/code\u003e folder) that you can look at.\n\nThe demo uses some extra tools that are not needed in your projects: [Prism](https://prismjs.com/) and [js-beautify)](https://beautifier.io/).\nFor better clarity, they area managed with dedicated files, all contained in \u003ccode\u003edemo/demo-assets\u003c/code\u003e folder.\n\nFor the same reason, both [Bootstrap](https://getbootstrap.com) and [JQuery](https://jquery.com/) are loaded from CDNs when needed.\n\nAll the css and the js files really related to FileUploader are located in \u003ccode\u003edemo/css\u003c/code\u003e and \u003ccode\u003edemo/js\u003c/code\u003e folders. \n\n\n### Demo pages structure\n\nEach demo page consists of 5 boxes:\n\n* The first is the real demo, which is an example of a FileUploader implementation\n* The **Original Markup** box contains the html code used to activate FileUploader\n* The **Javascript** box contains the code that calls the ES6 FileUploader library and instantiates the demo. The code is located in the JS file shown in parentheses  \n* The **Generated markup** box contains the html code after Fileuploader parsing\n* The last box, **Parsed FileUploader options**, contains the object generated merging (in this order):\n    * the default options object (in `src/_default_options.js`)\n    * the options set when FileUploader was instantiated (you can see them in the *Javascript* box)\n    * the configuration retrieved from data attributes of `data-file-uploader` element. This object is the same you can see in the browser console, and both them are visible only when `debug` option is set to `true`.\n\n\n\n\n## TODO\n\nThere is a long list of future implementation and fix I've planned, take a look at \u003chttps://github.com/massimo-cassandro/js-file-uploader/issues/4\u003e.\n\n\n## References (and inspirations)\n- \u003chttps://css-tricks.com/drag-and-drop-file-uploading/\u003e\n- \u003chttps://tympanus.net/codrops/2015/09/15/styling-customizing-file-inputs-smart-way/\u003e\n- \u003chttps://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation#Limiting_the_size_of_a_file_before_its_upload\u003e\n- \u003chttps://www.smashingmagazine.com/2018/01/drag-drop-file-uploader-vanilla-js/\u003e\n- \u003chttps://codepen.io/therealDaze/pen/ZaoErp\u003e\n- \u003chttps://github.com/gridstack/gridstack.js\u003e\n- \u003chttps://developer.mozilla.org/it/docs/Web/API/HTML_Drag_and_Drop_API\u003e\n- \u003chttps://www.html5rocks.com/en/tutorials/dnd/basics/\u003e\n- \u003chttps://kryogenix.org/code/browser/custom-drag-image.html\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmassimo-cassandro%2Fjs-file-uploader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmassimo-cassandro%2Fjs-file-uploader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmassimo-cassandro%2Fjs-file-uploader/lists"}