简体中文

上传

一个上传工具,拥有了两套预设的使用方法,并提供了一系列丰富的方法来让你自定义视图和交互。

基础
/**
 * Author: ひまわり(dtysky<dtysky@outlook.com>)
 * Github: https://github.com/dtysky
 * Created: 2017/3/6
 */
import React, {Component} from 'react';
import {Upload, Checkbox} from 'hana-ui';
import ExampleBlock from 'demo/ExampleBlock';

/**
 * @en
 * Base
 *
 * Base example with tow predefined view type and mode.
 *
 * @cn
 * 基础
 *
 * 基础例子,展示了两种不同的显示类型以及几种模式。
 *
 */
export default class ExampleBase extends Component {
  state = {
    baseAuto: false,
    baseMultiple: true,
    boxAuto: false,
    boxMultiple: true
  };

  render() {
    const {
      baseAuto,
      baseMultiple,
      boxAuto,
      boxMultiple
    } = this.state;

    return (
      <div>
        <ExampleBlock
          en={
            <p>View: base</p>
          }
          cn={
            <p>显示类型: base</p>
          }
        >
          <Checkbox
            style={{
              marginRight: 24
            }}
            label={'auto'}
            checked={baseAuto}
            onChange={() => this.setState({baseAuto: !baseAuto})}
          />
          <Checkbox
            label={'multiple'}
            checked={baseMultiple}
            onChange={() => this.setState({baseMultiple: !baseMultiple})}
          />
          <div
            style={{
              width: 320
            }}
          >
            <Upload
              auto={baseAuto}
              multiple={baseMultiple}
              url={'/upload'}
              withCredentials
            />
          </div>
        </ExampleBlock>

        <ExampleBlock
          en={
            <p>View: box</p>
          }
          cn={
            <p>显示类型: box</p>
          }
        >
          <Checkbox
            style={{
              marginRight: 24
            }}
            label={'auto'}
            checked={boxAuto}
            onChange={() => this.setState({boxAuto: !boxAuto})}
          />
          <Checkbox
            label={'multiple'}
            checked={boxMultiple}
            onChange={() => this.setState({boxMultiple: !boxMultiple})}
          />
          <div
            style={{
              width: 680,
              height: 240
            }}
          >
            <Upload
              view={'box'}
              auto={boxAuto}
              multiple={boxMultiple}
              url={'/upload'}
              withCredentials
            />
          </div>
        </ExampleBlock>
      </div>
    );
  }
}

基础例子,展示了两种不同的显示类型以及几种模式。

显示类型: base

显示类型: box

Select
Upload
方法
/**
 * Author: ひまわり(dtysky<dtysky@outlook.com>)
 * Github: https://github.com/dtysky
 * Created: 2017/3/9
 */
import React, {Component} from 'react';
import {Upload, Checkbox, Text} from 'hana-ui';
import ExampleBlock from 'demo/ExampleBlock';

/**
 * @en
 * Methods
 *
 * hana provides some methods to make file upload more flexible.
 *
 * Property `type` could constants the file type when selecting,
 * and the `disable` could disable this component.
 * If you want more constants after selecting, please check the `filterFileObj`.
 *
 * Use `parseFileObj` to add your custom attributes to file-object.
 *
 * @cn
 * 方法
 *
 * hana提供了一些方法来使得文件上传工作更加丰富多彩。
 *
 * `type`属性可以约束文件在`选择时`的类型,`disabled`则可以禁用上传组件。
 * 如果想在做出选择后进行更多的约束,你可以使用`filterFileObj`方法来进行过滤。
 *
 * `parseFileObj`方法则可以为文件对象添加自定义的属性,比如传输时的数据(详见属性定义)。
 */
export default class ExampleMethods extends Component {
  state = {
    type: '*',
    disabled: false,
    enableFilter: false,
    filterNameRegex: '.*\\.png
    
, enableParser: false, modifiedFileName: 'hayami' }; render() { const { type, disabled, enableFilter, filterNameRegex, enableParser, modifiedFileName } = this.state; const filter = file => { if (!enableFilter) { return true; } return new RegExp(filterNameRegex, 'g').test(file.name); }; const parser = () => { if (!enableParser) { return {}; } return {name: modifiedFileName}; }; return ( <div> <ExampleBlock> <div style={{ width: 420, marginBottom: 24 }} > <Checkbox style={{ marginRight: 24 }} label={'disabled'} checked={disabled} onChange={() => this.setState({disabled: !disabled})} /> <div style={{ display: 'inline-block', marginLeft: 24 }} > <Text icon={'type'} value={type} onChange={(e, value) => this.setState({type: value})} /> </div> </div> <div style={{ width: 420, marginBottom: 24 }} > <Checkbox label={'enableFilter'} checked={enableFilter} onChange={() => this.setState({enableFilter: !enableFilter})} /> <div style={{ display: 'inline-block', marginLeft: 24 }} > <Text icon={'filterNameRegex'} value={filterNameRegex} onChange={(e, value) => this.setState({filterNameRegex: value})} /> </div> </div> <div style={{ width: 460, marginBottom: 24 }} > <Checkbox label={'enableParser'} checked={enableParser} onChange={() => this.setState({enableParser: !enableParser})} /> <div style={{ display: 'inline-block', marginLeft: 24 }} > <Text icon={'modifiedFileName'} value={modifiedFileName} onChange={(e, value) => this.setState({modifiedFileName: value})} /> </div> </div> <div style={{ width: 320 }} > <Upload auto={false} multiple disabled={disabled} type={type} filterFileObj={filter} parseFileObj={parser} url={'/upload'} withCredentials /> </div> </ExampleBlock> </div> ); } }

hana提供了一些方法来使得文件上传工作更加丰富多彩。

type属性可以约束文件在选择时的类型,disabled则可以禁用上传组件。 如果想在做出选择后进行更多的约束,你可以使用filterFileObj方法来进行过滤。

parseFileObj方法则可以为文件对象添加自定义的属性,比如传输时的数据(详见属性定义)。

type

filterNameRegex

modifiedFileName

定制化
/**
 * Author: ひまわり(dtysky<dtysky@outlook.com>)
 * Github: https://github.com/dtysky
 * Created: 2017/3/10
 */
import React, {Component} from 'react';
import {UploadBase, Button} from 'hana-ui';
import cx from 'classnames';
import ExampleBlock from 'demo/ExampleBlock';

/**
 * @en
 * Customizations
 *
 * hana knows these two predefined view types may not meet your demand,
 * there is a way to customize your view.
 *
 * In this way, property `renderContent` is the most important method,
 * hana will pass all current files to her, and expect a `node` as result.
 *
 * You could bind some methods to this `node`,
 * and call methods of `Upload` component by `ref` in them.
 *
 * hana provides following methods:
 *
 * 1. `triggerChoose`: () => void,bring up the file selection dialog
 * 2. `uploadFiles`: files: Array => void, upload all files of `files`
 * 3. `abortFiles`: files: Array => void, abort all files' uploading of `files`
 * 4. `deleteFiles`: files: Array => void, delete all files of `files`
 *
 * @cn
 * 定制化
 *
 * hana也觉得这两种基础的视图无法满足很多需求,所以提供了一种方式来自定义显示的元素。
 *
 * 在这种方式中,核心的方法是`renderContent`属性,其传入当前所有的文件作为参数,返回要显示的组件。
 * 你可以向组件中的元素绑定一些方法,并在这些方法中使用引用`ref`调用`Upload`组件中的方法,以此完成需要的操作。
 *
 * hana提供了如下几个方法:
 * 1. `triggerChoose`:() => void,触发文件选择,调用后弹出文件选择器
 * 2. `uploadFiles`:files: Array => void,上传`files`中的所有文件
 * 3. `abortFiles`:files: Array => void,取消上传`files`中的所有文件
 * 4. `deleteFiles`:files: Array => void,删除`files`中的所有文件
 */
export default class ExampleCustom extends Component {
  parseFile = file => {
    const preview = {};

    if (/^image.*/.test(file.type)) {
      const reader = new FileReader();
      reader.onload = () => {
        preview.image = reader.result;
        this.forceUpdate();
      };
      reader.readAsDataURL(file);
    }
    return {preview};
  };

  handleChoose = () => {
    this.refs.upload.triggerChoose();
  };

  handleUpload = files => {
    this.refs.upload.uploadFiles(files);
  };

  handleAbort = files => {
    this.refs.upload.abortFiles(files);
  };

  handleClear = files => {
    this.refs.upload.deleteFiles(files);
  };

  render() {
    return (
      <div>
        <ExampleBlock>
          <UploadBase
            ref={'upload'}
            auto={false}
            parseFileObj={this.parseFile}
            multiple
            url={'/upload'}
            renderContent={this.renderContent}
          />
        </ExampleBlock>
      </div>
    );
  }

  renderContent = files => (
    <div>
      {this.renderActions(files)}
      {this.renderList(files)}
    </div>
  );

  renderActions = files => (
    <div>
      <Button
        onClick={this.handleChoose}
        style={{
          marginRight: 8
        }}
      >
        Select
      </Button>
      <Button
        onClick={() => this.handleUpload(files)}
        style={{
          marginRight: 8
        }}
      >
        Upload
      </Button>
      <Button
        onClick={() => this.handleAbort(files)}
        style={{
          marginRight: 8
        }}
      >
        Abort
      </Button>
      <Button
        onClick={() => this.handleClear(files)}
      >
        Clear
      </Button>
    </div>
  );

  renderList = files => (
    <div
      className={cx(
        'hana-upload-box-list'
      )}
      style={{
        border: '1px solid #ddd',
        width: 480,
        height: 240,
        borderRadius: 6,
        marginTop: 4
      }}
    >
      {
        files.map(file =>
          this.renderListItem(file)
        )
      }
    </div>
  );

  renderListItem = file => (
    <div
      key={file.index}
      className={cx(
        'hana-upload-box-list-item'
      )}
    >
      {
        file.preview.image
          ? (
          <div
            className={cx(
              'hana-upload-box-list-item-preview'
            )}
            style={{backgroundImage: `url(${file.preview.image})`}}
          >
          </div>
        )
        : (
          <div
            className={cx(
              'hana-upload-box-list-item-icon'
            )}
          >
          </div>
        )
      }
      <div
        className={cx(
          'hana-upload-box-list-item-content'
        )}
      >
        <div
          className={cx(
            'hana-upload-box-list-item-progress'
          )}
        >
          <div
            className={cx(
              `hana-upload-box-list-item-progress-${file.state}`
            )}
            style={{
              width: `${file.percent}%`
            }}
          >
          </div>
          <div
            className={cx(
              'hana-upload-box-list-item-progress-after'
            )}
            style={{
              width: `${100 - file.percent}%`
            }}
          >
          </div>
        </div>
        <div
          className={cx(
            'hana-upload-box-list-item-name'
          )}
        >
          {file.name}
        </div>
      </div>
    </div>
  );
}

hana也觉得这两种基础的视图无法满足很多需求,所以提供了一种方式来自定义显示的元素。

在这种方式中,核心的方法是renderContent属性,其传入当前所有的文件作为参数,返回要显示的组件。 你可以向组件中的元素绑定一些方法,并在这些方法中使用引用ref调用Upload组件中的方法,以此完成需要的操作。

hana提供了如下几个方法:

  1. triggerChoose:() => void,触发文件选择,调用后弹出文件选择器
  2. uploadFiles:files: Array => void,上传files中的所有文件
  3. abortFiles:files: Array => void,取消上传files中的所有文件
  4. deleteFiles:files: Array => void,删除files中的所有文件

属性说明

属性名 类型 默认值 说明
view enum:
 'base'
 'box'
'base' 预设的显示类型。
url * string '' 所有文件上传时默认使用的接口,当然,hana也提供了方式为每个文件单独设置接口,详见parseFileObj属性。
auto bool true 是否开启自动上传,若开启,文件将会在添加后自动上传。
multiple bool false 是否开启多选模式。
type string '*' 可选文件的类型,等价于HTML规范中input元素中的accept属性。
disabled bool false 是否要禁用上传功能。
parseFileObj function nop 当文件被选择后、添加到队列前执行的回调,返回一个对象,hana通过这个返回值来为生成的文件对象添加你想要的属性。 若想添加文件独有的urldataheader等,可以在此处设置。
file => Object
filterFileObj function () => true 当文件被选择后、添加到队列前执行的回调,返回一个Bool值,用于决定是否将该文件添加到队列中。
file => bool
data object {} 所有文件上传时默认使用的数据域,独立设置同url中的方法。
headers object {} 所有文件上传时默认使用的请求头,独立设置同url中的方法。
onChoose function nop 当文件被添加到队列后触发的回调。
fileObj => void
onStart function nop 文件开始传输之前触发的回调。
fileObj => void
onProgress function nop 文件传输过程中触发的回调。
(event, fileObj) => void
onSuccess function nop 文件传输成功时触发的回调。
(response, fileObj) => void
onError function nop 文件传输出错时触发的回调。
(error, response, fileObj) => void
withCredentials bool false 上传请求时是否携带cookie.
renderContent function 一个用于自定义视图的方法,类似于传统意义上的children属性, 她提供一个当前所有文件的列表,期望返回一个node,此node将会替代默认的视图被渲染到DOM上。
hana明白你的疑惑,在这种模式下,必须有一些上传相关的核心方法被提供, 关于这些方法,hana已经很详细地写到了最后一个例子中,请仔细阅读。
files => node

未在文档中说明的属性将会被自动加到根元素或form元素上。

文件对象

基础属性

名称 说明
file 原始文件对象
name 文件名称
size 文件大小
type 文件类型
index 文件的序号
uid 文件id
percent 文件上传进度
status 文件状态
abort 用于取消上传的函数
state 文件状态,init/uploading/error/success
response 文件上传响应
error 文件上传错误

可选属性

名称 说明
url 上传接口
data 数据域
headers 请求头
withCredentials 是否传送cookie
onProgress 上传时回调
onError 上传出错回调
onSuccess 上传成功回调