Upload 上传组件

如果项目中使用的是 0.x 版本的基础组件(@icedesign/base, @ali/ice, @alife/next),请在左侧导航顶部切换组件版本。

安装方法

  1. 在命令行中执行以下命令npm install @alifd/next@latest -S

开发指南

何时使用

用户根据提示将自己本地的相应信息(包含本地和云储存)上传到网站,上传组件可以帮助用户对上传过程和上传结果有预期,并可以更改或撤销上传行为。 参考文章: 1. Upload 组件的设计思想 2. Fusion Upload组件对接阿里云OSS/七牛/又拍

API

Upload

参数说明类型默认值
action上传的地址String-
shape上传按钮形状可选值:'card'Enum-
accept接受上传的文件类型 (image/png, image/jpg, .doc, .ppt) 详见 input accept attributeString-
data上传额外传参Object/Function-
headers设置上传的请求头部Object-
withCredentials是否允许请求携带 cookieBooleantrue
beforeUpload可选参数, 详见 beforeUpload签名:Function(file: Object, options: Object) => Boolean/Object/Promise参数:file: {Object} 所有文件options: {Object} 参数返回值:{Boolean/Object/Promise} 返回值作用见demoFunctionfunc.noop
onProgress上传中签名:Function() => voidFunctionfunc.noop
onSuccess可选参数,上传成功回调函数,参数为请求下响应信息以及文件签名:Function(file: Object, value: Array) => void参数:file: {Object} 文件value: {Array} 值Functionfunc.noop
onError可选参数,上传失败回调函数,参数为上传失败的信息、响应信息以及文件签名:Function(file: Object, value: Array) => void参数:file: {Object} 出错的文件value: {Array} 当前值Functionfunc.noop
children子元素ReactNode-
timeout设置上传超时,单位msNumber-
method上传方法可选值:'post', 'put'Enum'post'
request自定义上传方法签名:Function(option: Object) => Object参数:option: {Object} null返回值:{Object} object with abort methodFunction-
name文件名字段String-
onSelect选择文件回调签名:Function() => voidFunctionfunc.noop
onDrop放文件签名:Function() => voidFunctionfunc.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最大文件上传个数NumberInfinity
dragable可选参数,是否支持拖拽上传,ie10+ 支持。Boolean-
useDataURL可选参数,是否本地预览Boolean-
disabled可选参数,是否禁用上传功能Boolean-
onChange上传文件改变时的状态签名:Function(info: Object) => void参数:info: {Object} 文件事件对象Functionfunc.noop
afterSelect可选参数, 用于校验文件,afterSelect仅在 autoUpload=false 的时候生效,autoUpload=true时,可以使用beforeUpload完全可以替代该功能.签名:Function(file: Object) => Boolean参数:file: {Object} null返回值:{Boolean} 返回false会阻止上传,其他则表示正常Functionfunc.noop
onRemove移除文件回调函数签名:Function(file: Object) => Boolean/Promise参数:file: {Object} 文件返回值:{Boolean/Promise} 返回 false、Promise.resolve(false)、 Promise.reject() 将阻止文件删除Functionfunc.noop
autoUpload自动上传Booleantrue
progressProps透传给Progress propsObject-

Upload.Card

继承 Upload 的 API,除非特别说明

参数说明类型默认值
onPreview点击图片回调签名:Function() => voidFunctionfunc.noop
onChange改变时候的回调签名:Function() => voidFunctionfunc.noop
onRemove点击移除的回调签名:Function() => voidFunction-
onCancel取消上传的回调签名:Function() => voidFunction-

Upload.Dragger

IE10+ 支持。继承 Upload 的 API,除非特别说明

Upload.Selecter

底层能力 可自定义样式的文件选择器

参数说明类型默认值
disabled是否禁用上传功能Boolean-
multiple是否支持多选文件,ie10+ 支持。开启后按住 ctrl 可选择多个文件Booleanfalse
dragable是否支持拖拽上传,ie10+ 支持。Boolean-
accept接受上传的文件类型 (image/png, image/jpg, .doc, .ppt) 详见 input accept attributeString-
onSelect文件选择回调签名:Function() => voidFunctionfunc.noop
onDragOver拖拽经过回调签名:Function() => voidFunctionfunc.noop
onDragLeave拖拽离开回调签名:Function() => voidFunctionfunc.noop
onDrop拖拽完成回调签名:Function() => voidFunctionfunc.noop

Method

Upload.Uploader

底层能力 文件上传核心功能let uploader = new Upload.Uploader(options);

options

参数说明类型默认值
action上传的地址String-
data上传额外传参Object/Function-
headers设置上传的请求头部Object-
withCredentials是否允许请求携带 cookieBooleanfalse
onProgress上传中签名:Function() => voidFunctionnoop
onSuccess上传成功回调函数,参数为请求下响应信息以及文件签名:Function() => voidFunctionnoop
onError可选参数,上传失败回调函数,参数为上传失败的信息、响应信息以及文件签名:Function() => voidFunctionnoop

自定义Request

某些场景下需要自定义Request,例如对接AWS S3 jd-sdk or aliyun oss sdk,. Upload 支持 传入自定义的 request方法.

  1. function customRequest(option) {
  2. /* coding here */
  3. return {abort() {/* coding here */}};
  4. }
  5. <Upload request={customRequest}/>

customRequest被传入一个 object,包含以下属性:

  • onProgress: (event: { percent: number }): void

  • onError: (event: Error, body?: Object): void

  • onSuccess: (body: Object): void

  • data: Object // 额外的数据

  • filename: String // 文件名

  • file: File // 原生File对象

  • withCredentials: Boolean // 是否携带cookie

  • action: String // 请求地址

  • method: String // 请求类型 post/put

  • timeout: Number // 超时

  • headers: Object // 请求头

request需要返回一个包含abort方法的对象,用于中断上传

  • abort(file?: File) => void: abort the uploading file

具体实现参照 Upload 默认request方法: https://github.com/alibaba-fusion/next/blob/master/src/upload/runtime/request.jsx

ErrorCode

ErrorCode含义
EXCEED_LIMIT当设置了limit, 选中的文件 + 已上传的文件 > limit 报错
BEFOREUPLOAD_REJECTBeforeUpload中返回了 false/Promise.resolve(false)/Promise.reject()
RESPONSE_FAIL返回提响应错误

所有的值在Upload.ErrorCode.

onChange 返回结构

  1. {
  2. uid: 'uid', // 文件唯一标识
  3. name: 'xx.png' // 文件名
  4. state: 'done', // 状态有:selected uploading done error
  5. response: {"success":true} // 服务端响应内容
  6. url: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg',
  7. imgURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg', // 头像(可选)
  8. downloadURL: 'https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg' // 下载(可选)
  9. }

接口 response 返回数据格式要求

  1. {
  2. "success": true,
  3. "message": "上传成功", // success=false 时候可以展示错误
  4. "url": "https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg" // 返回结果
  5. "imgURL": "https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg", // 图片预览地址 (非必须)
  6. "downloadURL": "https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg", // 文件下载地址 (非必须)
  7. }

后端数据格式化

通过 formatter 将来自后端的不规则数据转换为符合组件要求的数据格式

  • 假设 服务器的响应数据如下
  1. {
  2. "status": "success", // 上传成功返回码
  3. "img_src": "https://img.alicdn.com/tps/TB19O79MVXXXXcZXVXXXXXXXXXX-1024-1024.jpg", // 图片链接
  4. }
  • 转换方法
  1. <Upload
  2. action="http://127.0.0.1:3001/upload"
  3. formatter={(res, file) => {
  4. // 函数里面根据当前服务器返回的响应数据
  5. // 重新拼装符合组件要求的数据格式
  6. return {
  7. success: res.status === 'success',
  8. url: res.img_src,
  9. }
  10. }}
  11. />

Upload 服务端代码样例

Next Upload组件上传文件使用的multipart/form-data方式上传文件,具体实现是在支持FormData对象的浏览器中使用xhr对象发送formdata。在不支持FormData对象的浏览器如IE9, 使用iframe原生表单实现。

各个语言的服务端框架,必然是可以处理multipart/form-data类型的请求,并解析出文件。一下给出两种语言的样例代码

IE9兼容性

  • ie9 下用因为使用 iframe 作为无刷新上传方案,必须保证表单页面的域名和上传的服务器端的域名相同。

  • ie9 下服务器端返回数据需要设置头部 context-typetext/html,不要设置为 application/json

  • 如果只是一级域名相同(taobao.com 为一级域名 shop.taobao.com 为二级域名),可以通过降域的方式实现跨域上传。

假设你表单页面的域是:shop.taobao.com,而上传的服务器端路径却是 upload.taobao.com。服务端返回必须带额外script标签

  1. <script>document.domain="taobao.com";</script>
  2. {"status":1,"type":"ajax","name":"54.png","url":".\/files\/54.png"}

iframe上传会额外传递参数 _documentDomain 方便你设置域名

ARIA and KeyBoard

按键说明
Enter1.当组件获取焦点时,按下Enter就可以选择文件上传 2.删除上传图片

代码示例

文件上传

提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图1

查看源码在线预览

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接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图2

查看源码在线预览

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接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图3

查看源码在线预览

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接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图4

查看源码在线预览

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',
            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'
        }]}
    />, 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);
}

自定义上传参数

通过 data 控制自定义参数

提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图5

查看源码在线预览

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);
}

拖拽上传

提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

提醒: 拖拽上传不适合视障人士使用,有无障碍需求的项目慎用

Upload 上传组件 - 图6

查看源码在线预览

import { Upload } from '@alifd/next';

ReactDOM.render((
    <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}
    />
), mountNode);

function onDragOver() {
    console.log('dragover callback');
}

function onDrop(fileList) {
    console.log('drop callback : ', fileList);
}

提交上传

通过按钮点击提交上传

提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图7

查看源码在线预览

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接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图8

查看源码在线预览

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接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图9

查看源码在线预览

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接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图10

查看源码在线预览

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接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图11

查看源码在线预览

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>&nbsp;&nbsp;
                    <Button onClick={this.getValues} type="primary" style={{margin: '0 0 10px'}}>Get Data</Button>&nbsp;&nbsp;
                    <Button onClick={() => this.field.reset()} type="primary" style={{margin: '0 0 10px'}}>Reset</Button>&nbsp;&nbsp;
                    <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接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图12

查看源码在线预览

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);
}

上传前预处理

使用beforeUpload去控制上传行为

提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload接口:

  1. 该接口仅作为测试使用,业务请勿使用
  2. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图13

查看源码在线预览

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);
}


裁剪上传

提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图14

查看源码在线预览

import { Upload, Button, Dialog } from '@alifd/next';
import Cropper from 'react-cropper';


function convertBase64UrlToFile(urlData) {

    const bytes = window.atob(urlData.split(',')[1]);

    const ab = new ArrayBuffer(bytes.length);
    const ia = new Uint8Array(ab);
    for (let i = 0; i < bytes.length; i++) {
        ia[i] = bytes.charCodeAt(i);
    }

    const blob = new Blob([ab], {type: 'image/png'});

    return new File([blob], 'test.png', {type: 'image/png'});
}

class App extends React.Component {
    constructor(props) {
        super(props);
        this.uploader = new Upload.Uploader({
            action: 'https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload',
            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 blob = convertBase64UrlToFile(data);
        const file = new File([blob], 'test.png', {type: 'image/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);

上传失败

Upload 上传组件 - 图15

查看源码在线预览

import { Upload, Button } from '@alifd/next';


const value = [
    {
        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'
    }
];

ReactDOM.render(
    <div>
        <Upload value={value} listType="text"> <Button>Upload</Button></Upload>

        <br />
        <Upload value={value} listType="card"> <Button>Upload</Button></Upload>

        <br />
        <Upload value={value} listType="image"> <Button>Upload</Button></Upload>
    </div>,
    mountNode
);

文件校验

afterSelect仅在 autoUpload=false 的时候生效autoUpload=true时,可以使用beforeUpload完全可以替代该功能.

提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload接口:

  1. 该接口仅作为测试使用,业务请勿使用
  2. 该接口仅支持图片上传,其他文件类型接口请自备

Upload 上传组件 - 图16

查看源码在线预览

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);

无障碍

提醒: https://www.easy-mock.com/mock/5b713974309d0d7d107a74a3/alifd/upload接口:

  1. 该接口仅作为测试使用,业务请勿使用
  1. 该接口仅支持图片上传,其他文件类型接口请自备
  1. 请参考ARIA and KeyBoard

Upload 上传组件 - 图17

查看源码在线预览

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);
}

相关区块

Upload 上传组件 - 图18

暂无相关区块