Default usage comes up with an upload button for manual instantiation of the upload and supports one file.
10 |11 | {` 12 |17 |15 | `} 16 |
├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── demo ├── App.jsx ├── Demo.jsx ├── index.js ├── main.css └── normalize.css ├── dist-modules ├── index.js └── styles.js ├── dist ├── xhr-uploader.js ├── xhr-uploader.js.map ├── xhr-uploader.min.js └── xhr-uploader.min.js.map ├── lib ├── index_template.ejs └── render.jsx ├── package.json ├── src ├── index.js └── styles.js ├── tests ├── .eslintrc ├── setup.js └── xhr-upload.spec.js ├── webpack.config.babel.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | gh-pages/ 2 | dist-modules/ 3 | dist/ 4 | build/ 5 | node_modules/ 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["prettier", "prettier/react"], 3 | "parserOptions": { 4 | "ecmaVersion": 6, 5 | "sourceType": "module", 6 | "ecmaFeatures": { 7 | "jsx": true 8 | } 9 | }, 10 | "env": { 11 | "es6": true, 12 | "browser": true, 13 | "mocha": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | 35 | build/ 36 | gh-pages/ 37 | dist-modules/ 38 | node_modules/ 39 | 40 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | demo/ 2 | lib/ 3 | tests/ 4 | src/ 5 | gh-pages/ 6 | dist/ 7 | .* 8 | karma.conf.js 9 | webpack.config.babel.js 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | cache: 5 | directories: 6 | - node_modules 7 | branches: 8 | only: 9 | - master 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, RMA Consulting 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of react-xhr-uploader nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React XHR Uploader 2 | 3 | [](https://badge.fury.io/js/react-xhr-uploader) 4 | [](https://travis-ci.org/rma-consulting/react-xhr-uploader) 5 | 6 | React component for uploading files with XMLHTTPRequest v2 7 | 8 | Check full documentation with examples at [https://harunhasdal.github.io/react-xhr-uploader](https://harunhasdal.github.io/react-xhr-uploader) 9 | 10 | Pull requests are welcome. 11 | 12 | ### How to run/develop locally 13 | 14 | Use `npm start` to run the webpack development server at localhost:8080. Hot module replacement is enabled. 15 | 16 | Use `npm test` to run the tests. Use `npm test:tdd` to run the tests continuously in watch mode. 17 | 18 | Use `npm run test:lint` to run ESLint checks. 19 | 20 | ### Example express server 21 | 22 | You will need a server that would accept post requests for multipart file uploads. Below is a sample express server to test out the examples. 23 | 24 | ```js 25 | const express = require('express'); 26 | const Busboy = require('busboy'); 27 | const fs = require('fs'); 28 | 29 | const port = 3000; 30 | const app = express(); 31 | 32 | app.all('/api/uploadfile', function(req, res, next) { 33 | res.header("Access-Control-Allow-Origin", "*"); 34 | res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type"); 35 | next(); 36 | }); 37 | 38 | app.post('/api/uploadfile', (req, res) => { 39 | const busboy = new Busboy({ headers: req.headers }); 40 | busboy.on('file', function(fieldname, file, filename) { 41 | let saveTo = __dirname + '/uploads/' + fieldname + '-' + filename + Date.now(); 42 | file.pipe(fs.createWriteStream(saveTo)); 43 | }); 44 | busboy.on('finish', function() { 45 | res.end('done'); 46 | }); 47 | res.on('close', function() { 48 | req.unpipe(busboy); 49 | }); 50 | req.pipe(busboy); 51 | }); 52 | 53 | app.listen(port, '0.0.0.0', function () { 54 | console.log(`Uploader server listening on port ${port}!`); 55 | }); 56 | 57 | ``` 58 | -------------------------------------------------------------------------------- /demo/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Demo from './Demo.jsx'; 3 | 4 | const App = () => ( 5 |
Demonstrating the XHR Uploader component
7 |Default usage comes up with an upload button for manual instantiation of the upload and supports one file.
10 |11 | {` 12 |17 |15 | `} 16 |
By default, the component uses POST method for file transfer. The component accepts the
21 |method22 |
property to specify different http method.
23 |24 | {` 25 |31 |29 | `} 30 |
You can enable automatic upload after drag and drop or file selection with
35 |auto36 |
property to get rid of the upload button.
37 |38 | {` 39 |45 |43 | `} 44 |
You can enable multiple file support with
49 |maxFiles50 |
property
51 |52 | {` 53 |60 |58 | `} 59 |
You can enable chunked file upload with
64 |chunksand
chunkSize
properties
65 |66 | {` 67 |76 |74 | `} 75 |
Pass more form data with
80 |formData81 |
82 | {` 83 |99 |97 | `} 98 |
The component accepts a
104 |style105 |
property as a javascript object to override the default styles of the component.
106 |Following is the default styles object the component uses. You can modify this object with your styles and pass in props.
107 |108 | {` 109 | const defaultStyles = { 110 | root: { 111 | border: '1px solid #CACACA', 112 | padding: 20 113 | }, 114 | dropTargetStyle: { 115 | border: '3px dashed #4A90E2', 116 | padding: 10, 117 | backgroundColor: '#ffffff', 118 | cursor: 'pointer' 119 | }, 120 | dropTargetActiveStyle: { 121 | backgroundColor: '#ccffcc' 122 | }, 123 | placeHolderStyle: { 124 | paddingLeft: '20%', 125 | paddingRight: '20%', 126 | textAlign: 'center' 127 | }, 128 | uploadButtonStyle: { 129 | width: '100%', 130 | marginTop: 10, 131 | height: 32, 132 | alignSelf: 'center', 133 | cursor: 'pointer', 134 | backgroundColor: '#D9EBFF', 135 | border: '1px solid #5094E3', 136 | fontSize: 14 137 | }, 138 | fileset: { 139 | marginTop: 10, 140 | paddingTop: 10, 141 | paddingBottom: 10, 142 | borderTop: '1px solid #CACACA' 143 | }, 144 | fileDetails: { 145 | paddingTop: 10, 146 | display: 'flex', 147 | alignItems: 'flex-start' 148 | }, 149 | fileName: { 150 | flexGrow: '8' 151 | }, 152 | fileSize: { 153 | 'float': 'right', 154 | flexGrow: '2', 155 | alignSelf: 'flex-end' 156 | }, 157 | removeButton: { 158 | alignSelf: 'flex-end' 159 | }, 160 | progress: { 161 | marginTop: 10, 162 | width: '100%', 163 | height: 16, 164 | WebkitAppearance: 'none' 165 | } 166 | }; 167 | `} 168 |169 |
170 | You do not need to pass in the entire style object in order to modify a particular inline style... E.g. if you need to override only 171 | the 172 |
173 |root174 |
style, then you can pass your styles object as follows:
175 |{` 176 | const myStyles = {root: {border: 'none', padding: 'none'}}; 177 |182 |181 | `}
XhrUploader will set the default styles above for all properties except for the ones that you override.
183 |For upload action controls, supply the following props as class names:
186 |cancelIconClass187 |
completeIconClass188 |
uploadIconClass189 |
If the above class names are not provided, default Font Awesome classes, e.g. 'fa fa-close', are stored.
190 |You will need to install FontAwesome if you would like to use their icons.
191 |194 | The upload progress bar is styled as HTML5 native progress bar of the host browser. To customise it, supply the following class 195 | name: 196 |
197 |progressClass198 |
{this.props.dropzoneLabel}
249 | 250 |