Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ lib
coverage
yarn.lock
es
package-lock.json
tmp/
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ React.render(<Upload />, container);
|component | "div"|"span" | "span"| wrap component name |
|supportServerRender | boolean | false| whether to support server render |
|onReady | function | | only call when supportServerRender is true, upload is rendered completely |
|action| string | | form action url |
|action| string &#124; function(file): string &#124; Promise&lt;string&gt; | | form action url |
|data| object/function(file) | | other data object to post or a function which returns a data object |
|headers| object | {} | http headers to post, available in modern browsers |
|accept | string | | input accept attribute |
Expand Down Expand Up @@ -113,7 +113,8 @@ abort(file?: File) => void: abort the uploading file

#### Download Popup Problem

In iframe uploader way, the content-type of response should be `text/plain` or `text/html`.[referense](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation)
In iframe uploader way, the content-type of response should be `text/plain` or `text/html`. [See more about
Content-Type Negotiation](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation)

What's more, in iframe mode, the response's status should always be `200 OK`, otherwise you might get an `Access is denied` error in IE 8/9.

Expand Down
1 change: 1 addition & 0 deletions examples/customRequest.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
placeholder
83 changes: 83 additions & 0 deletions examples/customRequest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* eslint no-console:0 */
import React from 'react';
import ReactDOM from 'react-dom';
import Upload from 'rc-upload';
import axios from 'axios';

const uploadProps = {
action: '/upload.do',
multiple: false,
data: { a: 1, b: 2 },
headers: {
Authorization: '$prefix $token',
},
onStart(file) {
console.log('onStart', file, file.name);
},
onSuccess(ret, file) {
console.log('onSuccess', ret, file.name);
},
onError(err) {
console.log('onError', err);
},
onProgress({ percent }, file) {
console.log('onProgress', `${percent}%`, file.name);
},
customRequest({
action,
data,
file,
filename,
headers,
onError,
onProgress,
onSuccess,
withCredentials,
}) {
// EXAMPLE: post form-data with 'axios'
const formData = new FormData();
if (data) {
Object.keys(data).map(key => {
formData.append(key, data[key]);
});
}
formData.append(filename, file);

axios
.post(action, formData, {
withCredentials,
headers,
onUploadProgress: ({ total, loaded }) => {
onProgress({ percent: Math.round(loaded / total * 100).toFixed(2) }, file);
},
})
.then(({ data: response }) => {
onSuccess(response, file);
})
.catch(onError);

return {
abort() {
console.log('upload progress is aborted.');
},
};
},
};

const Test = () => {
return (
<div
style={{
margin: 100,
}}
>
<div>
<Upload {...uploadProps}>
<button>开始上传</button>
</Upload>
</div>
</div>
);
};

ReactDOM.render(<Test />, document.getElementById('__react-content'));
1 change: 1 addition & 0 deletions examples/directoryUpload.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
placeholder
50 changes: 50 additions & 0 deletions examples/directoryUpload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint no-console:0 */

import React from 'react';
import ReactDOM from 'react-dom';
import Upload from 'rc-upload';

class Test extends React.Component {
constructor(props) {
super(props);
this.uploaderProps = {
action: '/upload.do',
data: { a: 1, b: 2 },
headers: {
Authorization: 'xxxxxxx',
},
directory: true,
beforeUpload(file) {
console.log('beforeUpload', file.name);
},
onStart: (file) => {
console.log('onStart', file.name);
// this.refs.inner.abort(file);
},
onSuccess(file) {
console.log('onSuccess', file);
},
onProgress(step, file) {
console.log('onProgress', Math.round(step.percent), file.name);
},
onError(err) {
console.log('onError', err);
},
};
}
render() {
return (<div
style={{
margin: 100,
}}
>

<div>
<Upload {...this.uploaderProps} ref="inner"><a>开始上传</a></Upload>
</div>

</div>);
}
}

ReactDOM.render(<Test/>, document.getElementById('__react-content'));
10 changes: 8 additions & 2 deletions examples/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,14 @@ class Test extends React.Component {
height: 500,
}}
>
<Upload {...this.uploaderProps} component="div" style={{ display: 'inline-block' }}>
<a>开始上传2</a></Upload>
<Upload
{...this.uploaderProps}
directory
component="div"
style={{ display: 'inline-block' }}
>
<a>开始上传2</a>
</Upload>
</div>
</div>

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"coverage": "jest --coverage && cat ./coverage/lcov.info | coveralls"
},
"devDependencies": {
"axios": "^0.18.0",
"co-busboy": "^1.3.0",
"coveralls": "^2.13.1",
"expect.js": "0.3.x",
Expand All @@ -53,8 +54,8 @@
"dependencies": {
"babel-runtime": "6.x",
"classnames": "^2.2.5",
"warning": "2.x",
"prop-types": "^15.5.7"
"prop-types": "^15.5.7",
"warning": "2.x"
},
"jest": {
"collectCoverageFrom": [
Expand Down
80 changes: 50 additions & 30 deletions src/AjaxUploader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import classNames from 'classnames';
import defaultRequest from './request';
import getUid from './uid';
import attrAccept from './attr-accept';
import traverseFileTree from './traverseFileTree';

class AjaxUploader extends Component {
static propTypes = {
Expand All @@ -14,6 +15,7 @@ class AjaxUploader extends Component {
prefixCls: PropTypes.string,
className: PropTypes.string,
multiple: PropTypes.bool,
directory: PropTypes.bool,
disabled: PropTypes.bool,
accept: PropTypes.string,
children: PropTypes.any,
Expand All @@ -22,6 +24,10 @@ class AjaxUploader extends Component {
PropTypes.object,
PropTypes.func,
]),
action: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
]),
headers: PropTypes.object,
beforeUpload: PropTypes.func,
customRequest: PropTypes.func,
Expand Down Expand Up @@ -54,16 +60,21 @@ class AjaxUploader extends Component {
}

onFileDrop = e => {
e.preventDefault();

if (e.type === 'dragover') {
e.preventDefault();
return;
}
const files = Array.prototype.slice.call(e.dataTransfer.files).filter(
let files = Array.prototype.slice.call(e.dataTransfer.files).filter(
file => attrAccept(file, this.props.accept)
);
this.uploadFiles(files);

e.preventDefault();
if (this.props.directory) {
traverseFileTree(e.dataTransfer.items, this.uploadFiles);
} else {
files = e.dataTransfer.files;
this.uploadFiles(files);
}
}

componentDidMount() {
Expand All @@ -75,7 +86,7 @@ class AjaxUploader extends Component {
this.abort();
}

uploadFiles(files) {
uploadFiles = (files) => {
const postFiles = Array.prototype.slice.call(files);
postFiles.forEach((file) => {
file.uid = getUid();
Expand All @@ -95,10 +106,9 @@ class AjaxUploader extends Component {
before.then((processedFile) => {
const processedFileType = Object.prototype.toString.call(processedFile);
if (processedFileType === '[object File]' || processedFileType === '[object Blob]') {
this.post(processedFile);
} else {
this.post(file);
return this.post(processedFile);
}
return this.post(file);
}).catch(e => {
console && console.log(e); // eslint-disable-line
});
Expand All @@ -117,28 +127,36 @@ class AjaxUploader extends Component {
if (typeof data === 'function') {
data = data(file);
}
const { uid } = file;
const request = props.customRequest || defaultRequest;
this.reqs[uid] = request({
action: props.action,
filename: props.name,
file,
data,
headers: props.headers,
withCredentials: props.withCredentials,
onProgress: onProgress ? e => {
onProgress(e, file);
} : null,
onSuccess: (ret, xhr) => {
delete this.reqs[uid];
props.onSuccess(ret, file, xhr);
},
onError: (err, ret) => {
delete this.reqs[uid];
props.onError(err, ret, file);
},
new Promise(resolve => {
const { action } = props;
if (typeof action === 'function') {
return resolve(action(file));
}
resolve(action);
}).then(action => {
const { uid } = file;
const request = props.customRequest || defaultRequest;
this.reqs[uid] = request({
action,
filename: props.name,
file,
data,
headers: props.headers,
withCredentials: props.withCredentials,
onProgress: onProgress ? e => {
onProgress(e, file);
} : null,
onSuccess: (ret, xhr) => {
delete this.reqs[uid];
props.onSuccess(ret, file, xhr);
},
onError: (err, ret) => {
delete this.reqs[uid];
props.onError(err, ret, file);
},
});
onStart(file);
});
onStart(file);
}

reset() {
Expand Down Expand Up @@ -176,7 +194,7 @@ class AjaxUploader extends Component {
render() {
const {
component: Tag, prefixCls, className, disabled,
style, multiple, accept, children,
style, multiple, accept, children, directory,
} = this.props;
const cls = classNames({
[prefixCls]: true,
Expand All @@ -203,6 +221,8 @@ class AjaxUploader extends Component {
key={this.state.uid}
style={{ display: 'none' }}
accept={accept}
directory={directory ? 'directory' : null}
webkitdirectory={directory ? 'webkitdirectory' : null}
multiple={multiple}
onChange={this.onChange}
/>
Expand Down
22 changes: 17 additions & 5 deletions src/IframeUploader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ class IframeUploader extends Component {
PropTypes.object,
PropTypes.func,
]),
action: PropTypes.string,
action: PropTypes.oneOfType([
PropTypes.string,
PropTypes.func,
]),
name: PropTypes.string,
}

Expand Down Expand Up @@ -142,7 +145,7 @@ class IframeUploader extends Component {
<body>
<form method="post"
encType="multipart/form-data"
action="${this.props.action}" id="form"
action="" id="form"
style="display:block;height:9999px;position:relative;overflow:hidden;">
<input id="input" type="file"
name="${this.props.name}"
Expand Down Expand Up @@ -247,9 +250,18 @@ class IframeUploader extends Component {
}
}
dataSpan.appendChild(inputs);
formNode.submit();
dataSpan.innerHTML = '';
onStart(file);
new Promise(resolve => {
const { action } = this.props;
if (typeof action === 'function') {
return resolve(action(file));
}
resolve(action);
}).then(action => {
formNode.setAttribute('action', action);
formNode.submit();
dataSpan.innerHTML = '';
onStart(file);
});
}

saveIframe = (node) => {
Expand Down
Loading