Skip to content

Commit

Permalink
feat(ajaxUploader): add transformFile option for transform file befor…
Browse files Browse the repository at this point in the history
…e request (react-component#194)

* feat(ajaxUploader): add transformFile option for transform file before request

* fix(ajaxUploader): modify default transformFile

* feat(ajaxUploader): remove transformFile params from callback
  • Loading branch information
lijinke666 authored and zombieJ committed Jul 31, 2019
1 parent 6e9a3bc commit bc4cefb
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 23 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ coverage
yarn.lock
es
package-lock.json
tmp/
tmp/
.history
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ React.render(<Upload />, container);
|customRequest | function | null | provide an override for the default xhr behavior for additional customization|
|withCredentials | boolean | false | ajax upload with cookie send |
|openFileDialogOnClick | boolean | true | useful for drag only upload as it does not trigger on enter key or click event |
|transformFile | function(file): Promise&lt;blob&gt; | | transform file before request |

#### onError arguments

Expand Down
2 changes: 1 addition & 1 deletion examples/customRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const uploadProps = {
// EXAMPLE: post form-data with 'axios'
const formData = new FormData();
if (data) {
Object.keys(data).map(key => {
Object.keys(data).forEach(key => {
formData.append(key, data[key]);
});
}
Expand Down
1 change: 1 addition & 0 deletions examples/transformFile.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
placeholder
59 changes: 59 additions & 0 deletions examples/transformFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* eslint no-console:0 */
import React from 'react';
import ReactDOM from 'react-dom';
import Upload from 'rc-upload';

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);
},
transformFile(file) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const canvas = document.createElement('canvas');
const img = document.createElement('img');
img.src = reader.result;
img.onload = () => {
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
canvas.toBlob(resolve);
};
};
});
},
};

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

ReactDOM.render(<Test />, document.getElementById('__react-content'));
50 changes: 30 additions & 20 deletions src/AjaxUploader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class AjaxUploader extends Component {
onProgress: PropTypes.func,
withCredentials: PropTypes.bool,
openFileDialogOnClick: PropTypes.bool,
transformFile: PropTypes.func,
}

state = { uid: getUid() }
Expand Down Expand Up @@ -132,7 +133,12 @@ class AjaxUploader extends Component {
}
const { props } = this;
let { data } = props;
const { onStart, onProgress } = props;
const {
onStart,
onProgress,
transformFile = (originFile) => originFile,
} = props;

if (typeof data === 'function') {
data = data(file);
}
Expand All @@ -145,26 +151,30 @@ class AjaxUploader extends Component {
}).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);
},
const transform = Promise.resolve(transformFile(file));
transform.then((transformedFile) => {
const requestOption = {
action,
filename: props.name,
data,
file: transformedFile,
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);
},
};
this.reqs[uid] = request(requestOption);
onStart(file);
});
onStart(file);
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default function upload(option) {
const formData = new FormData();

if (option.data) {
Object.keys(option.data).map(key => {
Object.keys(option.data).forEach(key => {
formData.append(key, option.data[key]);
});
}
Expand Down
58 changes: 58 additions & 0 deletions tests/uploader.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,4 +321,62 @@ describe('uploader', () => {
}, 100);
});
});

describe('transform file before request', () => {
let node;
let uploader;
beforeEach((done) => {
node = document.createElement('div');
document.body.appendChild(node);

ReactDOM.render(<Uploader />, node, function init() {
uploader = this;
done();
});
});

afterEach(() => {
ReactDOM.unmountComponentAtNode(node);
});

it('noes not affect receive origin file when transform file is null', (done) => {
const handlers = {};
const props = {
action: '/test',
onSuccess(ret, file) {
if (handlers.onSuccess) {
handlers.onSuccess(ret, file);
}
},
transformFile() {
return null;
},
};
ReactDOM.render(<Uploader {...props} />, node, function init() {
uploader = this;
const input = TestUtils.findRenderedDOMComponentWithTag(uploader, 'input');

const files = [{
name: 'success.png',
toString() {
return this.name;
},
}];

files.item = (i) => files[i];

handlers.onSuccess = (ret, file) => {
expect(ret[1]).to.eql(file.name);
expect(file).to.have.property('uid');
done();
};

Simulate.change(input, { target: { files } });

setTimeout(() => {
requests[0].respond(200, {}, `["","${files[0].name}"]`);
}, 100);
});
});
});
});

0 comments on commit bc4cefb

Please sign in to comment.