用户根据提示将自己本地的相应信息(包含本地和云储存)上传到网站,上传组件可以帮助用户对上传过程和上传结果有预期,并可以更改或撤销上传行为。
参考文章:
1. Upload 组件的设计思想
2. Fusion Upload组件对接阿里云OSS/七牛/又拍
import { Upload, Button, Icon } from '@alifd/next';
ReactDOM.render(<div>
<Upload
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
beforeUpload={beforeUpload}
onChange={onChange}
onSuccess={onSuccess}
multiple
defaultValue={[{
name: 'IMG.png',
state: 'done',
size: 1024,
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
fileURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}]}
>
<Button type="primary" style={{margin: '0 0 10px'}}>Upload File</Button>
</Upload>
<br/>
<Upload shape="card" style={{display: 'inline-block'}}>
Upload File
</Upload>
<Upload style={{display: 'inline-block', marginLeft: '5px'}}>
<div className="next-upload-card">
<Icon type="attachment" size="large"/>
<div className="next-upload-text">
Attachment
</div>
</div>
</Upload>
</div>, mountNode);
function beforeUpload(info) {
console.log('beforeUpload : ', info);
}
function onChange(info) {
console.log('onChange : ', info);
}
function onSuccess(info) {
console.log('onSuccess : ', info);
}
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button } from '@alifd/next';
const defaultValue = [{
uid: '0',
name: 'IMG.png',
state: 'done',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
size: 2000
}, {
uid: '1',
name: 'IMG.png',
percent: 50,
state: 'uploading',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}, {
uid: '2',
name: 'IMG.png',
state: 'error',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
errorMsg: 'fail to upload something'
}, {
uid: '3',
name: 'IMG.png',
state: 'error',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}];
ReactDOM.render(
<Upload
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
beforeUpload={beforeUpload}
onChange={onChange}
onSuccess={onSuccess}
listType="text"
defaultValue={defaultValue}>
<Button type="primary" style={{margin: '0 0 10px'}}>Upload File</Button>
</Upload>, mountNode);
function beforeUpload(info) {
console.log('beforeUpload : ', info);
}
function onChange(info) {
console.log('onChange : ', info);
}
function onSuccess(info) {
console.log('onSuccess : ', info);
}
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button } from '@alifd/next';
ReactDOM.render(
<Upload
listType="image"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
beforeUpload={beforeUpload}
onChange={onChange}
defaultValue={[{
uid: '0',
name: 'IMG.png',
state: 'done',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
size: 2000
}, {
uid: '1',
name: 'IMG.png',
percent: 50,
state: 'uploading',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}, {
uid: '2',
name: 'IMG.png',
state: 'error',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}, {
uid: '3',
name: 'IMG.png',
state: 'error',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
errorMsg: 'Fail to Upload something'
}]}
>
<Button type="primary" style={{margin: '0 0 10px'}}>Upload File</Button>
</Upload>, mountNode);
function beforeUpload(info) {
console.log('beforeUpload callback : ', info);
}
function onChange(info) {
console.log('onChange callback : ', info);
}
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload } from '@alifd/next';
ReactDOM.render(
<Upload.Card
listType="card"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
onPreview={onPreview}
onChange={onChange}
onSuccess={onSuccess}
onError={onError}
defaultValue={[{
uid: '0',
name: 'IMG.png',
state: 'done',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}, {
uid: '1',
name: 'IMG.png',
state: 'done',
url: 'https://gw.alicdn.com/tfs/TB1Y4ucuAL0gK0jSZFtXXXQCXXa-1020-510.jpg',
downloadURL: 'https://gw.alicdn.com/tfs/TB1Y4ucuAL0gK0jSZFtXXXQCXXa-1020-510.jpg',
imgURL: 'https://gw.alicdn.com/tfs/TB1Y4ucuAL0gK0jSZFtXXXQCXXa-1020-510.jpg'
}, {
uid: '2',
name: 'IMG.png',
state: 'done',
url: 'https://img.alicdn.com/tfs/TB1Y8vPtKbviK0jSZFNXXaApXXa-216-460.png',
downloadURL: 'https://img.alicdn.com/tfs/TB1Y8vPtKbviK0jSZFNXXaApXXa-216-460.png',
imgURL: 'https://img.alicdn.com/tfs/TB1Y8vPtKbviK0jSZFNXXaApXXa-216-460.png'
}, {
uid: '3',
name: 'IMG.png',
percent: 50,
state: 'uploading',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}, {
uid: '4',
name: 'IMG.png',
state: 'error',
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}]}
/>, mountNode);
function onPreview(info) {
console.log('onPreview callback : ', info);
}
function onChange(info) {
console.log('onChange callback : ', info);
}
function onSuccess(res, file) {
console.log('onSuccess callback : ', res, file);
}
function onError(file) {
console.log('onError callback : ', file);
}
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button } from '@alifd/next';
ReactDOM.render((
<Upload
listType="text"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
data={{token: 'abcd'}}
beforeUpload={beforeUpload}
onChange={onChange}
defaultValue={[{
name: 'IMG.png',
state: 'done',
size: 1024,
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}]}
>
<Button type="primary" style={{margin: '0 0 10px'}}>Upload File</Button>
</Upload>
), mountNode);
function beforeUpload(info) {
console.log('beforeUpload callback : ', info);
}
function onChange(info) {
console.log('onChange callback : ', info);
}
通过 data 控制自定义参数
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Icon, Button } from '@alifd/next';
function handleClick(e) {
e.stopPropagation();
// download template
}
ReactDOM.render((
<div>
<Upload.Dragger
listType="image"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
onDragOver={onDragOver}
onDrop={onDrop}
/>
<br/>
<Upload.Dragger
listType="image"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
onDragOver={onDragOver}
onDrop={onDrop}
>
<div className="next-upload-drag">
<p className="next-upload-drag-icon"><Icon type="upload"/></p>
<p className="next-upload-drag-text">click to <Button text onClick={handleClick}>download template</Button> or drag file here</p>
<p className="next-upload-drag-hint">supports docx, xls, PDF </p>
</div>
</Upload.Dragger>
</div>
), mountNode);
function onDragOver() {
console.log('dragover callback');
}
function onDrop(fileList) {
console.log('drop callback : ', fileList);
}
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
提醒: 拖拽上传不适合视障人士使用,有无障碍需求的项目慎用
import { Upload, Input } from '@alifd/next';
class App extends React.Component {
onPaste = (e) => {
e.preventDefault();
const files = e.clipboardData.files;
files.length && this.uploaderRef.selectFiles(files);
};
saveUploaderRef = (ref) => {
this.uploaderRef = ref.getInstance();
};
onChange = (value) => {
console.log(value);
};
render() {
return (<div>
<Input.TextArea style={{width: '100%', marginBottom: 10}} autoHeight={{minRows: 4}} onPaste={this.onPaste} />
<Upload
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
listType="image"
onChange={this.onChange}
ref={this.saveUploaderRef}
/>
</div>);
}
}
ReactDOM.render(<App/>, mountNode);
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button } from '@alifd/next';
class App extends React.Component {
saveUploaderRef = (ref) => {
this.uploaderRef = ref.getInstance();
};
onSubmit = () => {
this.uploaderRef.startUpload();
}
beforeUpload(info, options) {
console.log('beforeUpload callback : ', info, options);
return options;
}
render() {
return (
<div>
<Upload
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
autoUpload={false}
ref={this.saveUploaderRef}
listType="card"
beforeUpload={this.beforeUpload}
useDataURL
>
<Button>Upload</Button>
</Upload>
<br />
<Button type="primary" onClick={this.onSubmit}>Submit</Button>
</div>
);
}
}
ReactDOM.render(<App />, mountNode);
通过按钮点击提交上传
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button } from '@alifd/next';
const onError = (file, fileList) => {
console.log('Exceed limit', file, fileList);
};
ReactDOM.render((
<div>
<Upload
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
limit={2}
multiple
listType="text"
onError={onError}
defaultValue={[{
name: 'IMG.png',
state: 'done',
size: 1024,
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
fileURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}]}>
<Button type="primary" style={{margin: '0 0 10px'}}>Upload File</Button>
</Upload>
</div>
), mountNode);
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Dialog, Button } from '@alifd/next';
const beforeUpload = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const img = new Image();
img.onload = () => {
if (img.width <= 1200) {
resolve();
} else {
Dialog.alert({
content: `Image width ${img.width}px, Exceed limits!`,
closable: false,
title: 'Warning'
});
reject();
}
};
img.src = reader.result;
};
reader.readAsDataURL(file);
});
};
ReactDOM.render((
<Upload
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
limit={3}
multiple
beforeUpload={beforeUpload}
listType="text"
defaultValue={[{
name: 'IMG.png',
state: 'done',
size: 1024,
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
fileURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}]}
>
<Button type="primary" style={{margin: '0 0 10px'}}>Upload file</Button>
</Upload>
), mountNode);
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button, Field, Form } from '@alifd/next';
const FormItem = Form.Item;
const value = [{
name: 'pic.png',
fileName: 'pic.png',
state: 'done',
size: 1000,
downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
fileURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}];
class App extends React.Component {
field = new Field(this);
setValues = () => {
this.field.setValues({
upload: [...value]
});
};
getValues = () => {
const values = this.field.getValues();
console.log(values);
};
render() {
return (
<Form field={this.field}>
<FormItem required>
<Upload
listType="text"
name="upload"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
defaultValue={value}
>
<Button>Upload</Button>
</Upload>
</FormItem>
<div>
<Button onClick={this.setValues} type="primary" style={{margin: '0 0 10px'}}>Set Data</Button>
<Button onClick={this.getValues} type="primary" style={{margin: '0 0 10px'}}>Get Data</Button>
<Button onClick={() => this.field.reset()} type="primary" style={{margin: '0 0 10px'}}>Reset</Button>
<Button onClick={() => this.field.validate()} type="primary" style={{margin: '0 0 10px'}}>Validate</Button>
</div>
</Form>
);
}
}
ReactDOM.render(<App />, mountNode);
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button } from '@alifd/next';
ReactDOM.render([
<Upload
listType="text"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
beforeUpload={beforeUpload}
onChange={onChange}
key="1"
>
<Button type="primary" style={{margin: '0 0 10px'}}>Upload File</Button>
</Upload>,
<Upload
listType="text"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
beforeUpload={asyncBeforeUpload}
onChange={onChange}
key="2"
>
<Button type="secondary" style={{margin: '0 0 10px'}}>Async Call before Upload File</Button>
</Upload>,
<Upload
listType="text"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
beforeUpload={() => false}
onChange={onChange}
key="3"
>
<Button type="normal" style={{margin: '0 0 10px'}}>Prevent Upload</Button>
</Upload>,
<Upload
listType="text"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
beforeUpload={() => new Promise(resl => setTimeout(() => resl(false)))}
onChange={onChange}
key="4"
>
<Button type="primary" style={{margin: '0 0 10px'}}>Async Prevent Upload</Button>
</Upload>,
<Upload
listType="text"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
beforeUpload={() => {}}
onChange={onChange}
key="5"
>
<Button type="secondary" style={{margin: '0 0 10px'}}>Do nothing</Button>
</Upload>
], mountNode);
const requestOpts = {
action: 'https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload',
data: {osstoken: 1234},
headers: {'X-Requested-With': 12345}
};
async function ajax() {
return await new Promise(resolve => {
setTimeout(() => {
resolve(requestOpts);
}, 1e3);
});
}
function beforeUpload(file, options) {
console.log('beforeUpload callback : ', file, options);
return requestOpts;
}
async function asyncBeforeUpload(file, options) {
console.log('beforeUpload callback : ', file, options);
return await ajax();
}
function onChange(file) {
console.log('onChange callback : ', file);
}
使用beforeUpload去控制上传行为
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button } from '@alifd/next';
const extraRender = (file) => {
console.log(file);
return (<Button style={{marginLeft: 4}}>extra</Button>);
};
ReactDOM.render((
<Upload
listType="image"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
beforeUpload={beforeUpload}
onChange={onChange}
extraRender={extraRender}
defaultValue={[{
name: 'IMG.png',
state: 'done',
size: 100,
url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg'
}]}
>
<Button type="primary" style={{margin: '0 0 10px'}}>Upload File</Button>
</Upload>
), mountNode);
function beforeUpload(info) {
console.log('beforeUpload callback : ', info);
}
function onChange(info) {
console.log('onChange callback : ', info);
}
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button, Dialog } from '@alifd/next';
import Cropper from 'react-cropper';
function dataURL2File(dataURL, fileName){
const arr = dataURL.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
u8arr = new Uint8Array(bstr.length);
let n = bstr.length;
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
const blob = new Blob([u8arr], { type: mime });
// to File
blob.lastModifiedDate = new Date();
blob.name = fileName;
return blob;
};
class App extends React.Component {
constructor(props) {
super(props);
this.uploader = new Upload.Uploader({
action: 'http://127.0.0.1:6001/upload.do',
onSuccess: this.onSuccess,
name: 'file'
});
}
state = {
src: null,
visible: false,
img: null
};
onSuccess = (value) => {
console.log(value);
this.setState({
img: value.url
});
};
onSelect = (files) => {
const reader = new FileReader();
reader.onload = () => {
this.setState({
src: reader.result,
visible: true
});
};
reader.readAsDataURL(files[0]);
};
onCancel = () => {
this.setState({
visible: false
});
};
onOk = () => {
const data = this.cropperRef.getCroppedCanvas().toDataURL();
const file = dataURL2File(data, 'test.png');
// start upload
this.uploader.startUpload(file);
this.setState({
visible: false
});
};
saveCropperrRef = (ref) => {
this.cropperRef = ref;
};
render() {
return (
<div>
<Upload.Selecter onSelect={this.onSelect}
>
<Button>Select file</Button>
</Upload.Selecter>
<Dialog
visible={this.state.visible}
onCancel={this.onCancel}
onOk={this.onOk}
onClose={this.onCancel}
isFullScreen>
<Cropper
ref={this.saveCropperrRef}
src={this.state.src}
style={{height: 300, width: 400}}
/>
</Dialog>
<div><img src={this.state.img} style={{width: 100}}/></div>
</div>
);
}
}
ReactDOM.render(<App/>, mountNode);
提供了两种方案,如果不需要支持 IE 推荐方案1
import { Upload } from '@alifd/next';
class App extends React.Component {
beforeUpload = (file, options) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
// mock ajax to get host/OSSAccessKeyId/policy/signature/key
const dataFormAjaxResponse = {
host: 'post-test.oss-cn-hangzhou.aliyuncs.com',
OSSAccessKeyId:'6MKO******4AUk44',
policy:'eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8iXV19',
signature:'I2u57FWjTKqX/AE6doIdyff151E=',
key: 'user-dir/filename.jpg',
};
const { host, OSSAccessKeyId, policy, signature, key, domain, } = dataFormAjaxResponse;
// modify action and form data
options.action = `//${host}`;
options.data = {
key,
policy,
OSSAccessKeyId,
signature,
};
// save url to file object
file.tempUrl = `//${domain}/${key}`;
resolve(options);
}, 300);
});
}
onSuccess = (file, value) => {
console.log(file, value);
};
formatter = (res, file) => ({
success: true,
url: file.tempUrl
});
render() {
return (
<Upload
beforeUpload={this.beforeUpload}
onSuccess={this.onSuccess}
formatter={this.formatter}
shape="card"
>
oss demo
</Upload>
);
}
}
ReactDOM.render(<App/>, mountNode);
需要先从后端获取 host/OSSAccessKeyId/policy/signature/key 参数,修改action和data,再利用upload能力上层
因为 demo 中的 action 为 oss 测试地址,不支持直接上传,所以控制台会报Access-Control-Allow-Origin
的错误,真实环境中需要自己配置下访问控制
import { Upload, Button } from '@alifd/next';
class App extends React.Component {
saveUploaderRef = (ref) => {
this.uploaderRef = ref.getInstance();
};
onSubmit = () => {
this.uploaderRef.startUpload();
}
afterSelect(file) {
console.log(file);
return true; // return false will trigger onError warning & prevent upload
}
render() {
return (
<div>
<Upload
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
autoUpload={false}
ref={this.saveUploaderRef}
listType="text"
afterSelect={this.afterSelect}
>
<Button>Upload</Button>
</Upload>
<br />
<Button type="primary" onClick={this.onSubmit}>Submit</Button>
</div>
);
}
}
ReactDOM.render(<App />, mountNode);
afterSelect仅在 autoUpload=false 的时候生效 autoUpload=true时,可以使用beforeUpload完全可以替代该功能.
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
import { Upload, Button } from '@alifd/next';
ReactDOM.render([
<Upload
listType="text"
action="https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload"
accept="image/png, image/jpg, image/jpeg, image/gif, image/bmp"
beforeUpload={() => {}}
onChange={onChange}
key="5"
>
<Button type="secondary" style={{margin: '0 0 10px'}}>upload </Button>
</Upload>
], mountNode);
function onChange(info) {
console.log('onChange callback : ', info);
}
提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload
接口:
- 该接口仅作为测试使用,业务请勿使用
- 该接口仅支持图片上传,其他文件类型接口请自备
- 请参考
ARIA and KeyBoard
。
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
action | 上传的地址 | String | - |
shape | 上传按钮形状 可选值: 'card' |
Enum | - |
accept | 接受上传的文件类型 (image/png, image/jpg, .doc, .ppt) 详见 input accept attribute | String | - |
data | 上传额外传参 | Object/Function | - |
headers | 设置上传的请求头部 | Object | - |
withCredentials | 是否允许请求携带 cookie | Boolean | true |
beforeUpload | 可选参数, 详见 beforeUpload 签名: Function(file: Object, options: Object) => Boolean/Object/Promise 参数: file: {Object} 所有文件 options: {Object} 参数 返回值: {Boolean/Object/Promise} 返回值作用见demo |
Function | func.noop |
onProgress | 上传中 签名: Function() => void |
Function | func.noop |
onSuccess | 可选参数,上传成功回调函数,参数为请求下响应信息以及文件 签名: Function(file: Object, value: Array) => void 参数: file: {Object} 文件 value: {Array} 值 |
Function | func.noop |
onError | 可选参数,上传失败回调函数,参数为上传失败的信息、响应信息以及文件 签名: Function(file: Object, value: Array) => void 参数: file: {Object} 出错的文件 value: {Array} 当前值 |
Function | func.noop |
children | 子元素 | ReactNode | - |
timeout | 设置上传超时,单位ms | Number | - |
method | 上传方法 可选值: 'post', 'put' |
Enum | 'post' |
request | 自定义上传方法 签名: Function(option: Object) => Object 参数: option: {Object} null 返回值: {Object} object with abort method |
Function | - |
name | 文件名字段 | String | - |
onSelect | 选择文件回调 签名: Function() => void |
Function | func.noop |
onDrop | 放文件 签名: Function() => void |
Function | func.noop |
value | 文件列表 | Array | - |
defaultValue | 默认文件列表 | Array | - |
listType | 上传列表的样式 可选值: 'text'(文字) 'image'(图文) 'card'(卡片) |
Enum | - |
formatter | 数据格式化函数,配合自定义 action 使用,参数为服务器的响应数据,详见 formatter 签名: Function(response: Object, file: File) => void 参数: response: {Object} 返回 file: {File} 文件对象 |
Function | - |
limit | 最大文件上传个数 | Number | Infinity |
dragable | 可选参数,是否支持拖拽上传,ie10+ 支持。 |
Boolean | - |
useDataURL | 可选参数,是否本地预览 | Boolean | - |
disabled | 可选参数,是否禁用上传功能 | Boolean | - |
onChange | 上传文件改变时的状态 签名: Function(info: Object) => void 参数: info: {Object} 文件事件对象 |
Function | func.noop |
afterSelect | 可选参数, 用于校验文件,afterSelect仅在 autoUpload=false 的时候生效,autoUpload=true时,可以使用beforeUpload完全可以替代该功能. 签名: Function(file: Object) => Boolean 参数: file: {Object} null 返回值: {Boolean} 返回false会阻止上传,其他则表示正常 |
Function | func.noop |
onRemove | 移除文件回调函数 签名: Function(file: Object) => Boolean/Promise 参数: file: {Object} 文件 返回值: {Boolean/Promise} 返回 false、Promise.resolve(false)、 Promise.reject() 将阻止文件删除 |
Function | func.noop |
autoUpload | 自动上传 | Boolean | true |
progressProps | 透传给Progress props | Object | - |
isPreview | 是否为预览态 | Boolean | - |
renderPreview | 预览态模式下渲染的内容 签名: Function(value: number) => void 参数: value: {number} 评分值 |
Function | - |
继承 Upload 的 API,除非特别说明
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
onPreview | 点击图片回调 签名: Function() => void |
Function | func.noop |
onChange | 改变时候的回调 签名: Function() => void |
Function | func.noop |
onRemove | 点击移除的回调 签名: Function() => void |
Function | - |
onCancel | 取消上传的回调 签名: Function() => void |
Function | - |
IE10+ 支持。继承 Upload 的 API,除非特别说明
[底层能力] 可自定义样式的文件选择器
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
disabled | 是否禁用上传功能 | Boolean | - |
multiple | 是否支持多选文件,ie10+ 支持。开启后按住 ctrl 可选择多个文件 |
Boolean | false |
dragable | 是否支持拖拽上传,ie10+ 支持。 |
Boolean | - |
accept | 接受上传的文件类型 (image/png, image/jpg, .doc, .ppt) 详见 input accept attribute | String | - |
onSelect | 文件选择回调 签名: Function() => void |
Function | func.noop |
onDragOver | 拖拽经过回调 签名: Function() => void |
Function | func.noop |
onDragLeave | 拖拽离开回调 签名: Function() => void |
Function | func.noop |
onDrop | 拖拽完成回调 签名: Function() => void |
Function | func.noop |
[底层能力] 文件上传核心功能 let uploader = new Upload.Uploader([options]);
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
action | 上传的地址 | String | - |
data | 上传额外传参 | Object/Function | - |
headers | 设置上传的请求头部 | Object | - |
withCredentials | 是否允许请求携带 cookie | Boolean | false |
onProgress | 上传中 签名: Function() => void |
Function | noop |
onSuccess | 上传成功回调函数,参数为请求下响应信息以及文件 签名: Function() => void |
Function | noop |
onError | 可选参数,上传失败回调函数,参数为上传失败的信息、响应信息以及文件 签名: Function() => void |
Function | noop |
某些场景下需要自定义Request,例如对接AWS S3 jd-sdk or aliyun oss sdk,. Upload 支持 传入自定义的 request方法.
function customRequest(option) { /* coding here */ return {abort() {/* coding here */}}; } <Upload request={customRequest}/>
customRequest被传入一个 object,包含以下属性:
request需要返回一个包含abort方法的对象,用于中断上传
具体实现参照 Upload 默认request方法: https://github.com/alibaba-fusion/next/blob/master/src/upload/runtime/request.jsx
ErrorCode | 含义 |
---|---|
EXCEED_LIMIT | 当设置了limit, 选中的文件 + 已上传的文件 > limit 报错 |
BEFOREUPLOAD_REJECT | BeforeUpload中返回了 false/Promise.resolve(false)/Promise.reject() |
RESPONSE_FAIL | 返回提响应错误 |
所有的值在Upload.ErrorCode
.
{ uid: 'uid', // 文件唯一标识 name: 'xx.png' // 文件名 state: 'done', // 状态有:selected uploading done error response: {"success":true} // 服务端响应内容 url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg', imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg', // 头像(可选) downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg' // 下载(可选) }
{ "success": true, "message": "上传成功", // success=false 时候可以展示错误 "url": "https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg" // 返回结果 "imgURL": "https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg", // 图片预览地址 (非必须) "downloadURL": "https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg", // 文件下载地址 (非必须) }
通过 formatter
将来自后端的不规则数据转换为符合组件要求的数据格式
假设
服务器的响应数据如下{ "status": "success", // 上传成功返回码 "img_src": "https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg", // 图片链接 }
<Upload action="http://127.0.0.1:3001/upload" formatter={(res, file) => { // 函数里面根据当前服务器返回的响应数据 // 重新拼装符合组件要求的数据格式 return { success: res.status === 'success', url: res.img_src, } }} />
Next Upload组件上传文件使用的multipart/form-data
方式上传文件,具体实现是在支持FormData
对象的浏览器中使用xhr对象发送formdata。在不支持FormData
对象的浏览器如IE9, 使用iframe原生表单实现。
各个语言的服务端框架,必然是可以处理multipart/form-data
类型的请求,并解析出文件。一下给出两种语言的样例代码
context-type
为 text/html
,不要设置为 application/json
taobao.com
为一级域名 shop.taobao.com
为二级域名),可以通过降域的方式实现跨域上传。假设你表单页面的域是:shop.taobao.com,而上传的服务器端路径却是 upload.taobao.com。服务端返回必须带额外script标签
<script>document.domain="taobao.com";</script> {"status":1,"type":"ajax","name":"54.png","url":".\/files\/54.png"}
iframe上传会额外传递参数 _documentDomain
方便你设置域名
按键 | 说明 |
---|---|
Enter | 1.当组件获取焦点时,按下Enter 就可以选择文件上传 2.删除上传图片 |