@beisen-phoenix/upload

souce code

Usage no npm install needed!

<script type="module">
  import beisenPhoenixUpload from 'https://cdn.skypack.dev/@beisen-phoenix/upload';
</script>

README

上传组件

souce code

说明

本组件只包含上传逻辑与渲染上传按钮的部分。如果需要显示标准的文件列表,请对接 @beisen-phoenix/file-list 显示文件列表,如果要预览图片,请对接 @beisen-phoenix/img-preview 组件

upload目前有四个相关组件

为什么使用受控组件

在开发上传组件的过程中,发现业务场景比较多,我们不能通过一个组件满足所有的需求,所以对整个上传行为进行了一次拆分,期中本组件负责,从选择文件到上传过程中的逻辑,但是不负责渲染文件列表。

同时,因为上传的时候数据状态本身也比较复杂,通过受控组件的方式,把组件状态的变化实时的告知父组件,由父组件根据自身的情况对数据进行处理。所以 Upload 组件需要接受两个基本的参数

  • files: UploadFileType[] 文件列表
  • onChange: (files: UploadFileType[]) => void 当文件状态发生变化的时候的回调

期中 UploadFileType 的类型定义为


interface IParseResponse {
  (data: any): Partial<IUploadFileType>
}

interface UploadFileType {
  name: string; //文件名称
  status: EStatus; //当前状态
  mediaType: string; // 文件格式
  previewUrl?: string; //预览地址
  downloadUrl?: string; // 下载地址
  percent?: number; // 上传进度
  raw?: File; // 源文件数据
  id?: string; // 后端数据标识
  lid?: string; // 前端数据标识
}

参数 (interface 定义)

interface UploadProps {
  multiple?: boolean; // 是否允许多选
  maxSize?: number; // 文件体积限制
  maxFiles?: number; // 文件个数限制
  url?: Url; // 上传接口地址,支持post
  onError?: OnError; //发生错误回调
  children: JSX.Element; //children 上传按钮的react element
  files?: IUploadFileType[]; //文件列表
  onChange: OnChange; //文件状态发生变化时的回调
  onEachComplete?: OnEachComplete; //单个文件上传完成时的回调
  accept?: string | string[]; //接受的文件类型格式
  parseResponse?: IParseResponse;
  validator?: TValidator; //自定义的文件验证方法,在选择文件后调用,可以按照自己的需求过滤
}

接受的文件类型:参数accept

详细的信息请参考 https://github.com/okonet/attr-accept, 不过请注意 mime 类型在不同系统下表现是不一样的,比如CSV类型的文件在MacOS下是text/plain,但在window系统下是application/vnd.ms-excel。同时在一些场景下可能都不是mine类型。参考:https://github.com/react-dropzone/react-dropzone/issues/276

文件类型示例

  • .png 只接受png图片
  • *image/ ** 接受所有类型的图片
  • ["image/", "video/mp4"]* 只接受图片和mp4的视频

https://github.com/okonet/attr-accept/blob/master/test/index.js

关于id与lid

在文件数据中允许同时存在id与lid, lid是上传文件的名称+当前的时间戳,是为了方便识别当前上传的文件,当文件上传到服务器,就需要生成一个服务端的id,就是id所代表的意义。

示例

import React, { useState } from 'react';
import Upload, { UploadFileType } from '../../src';
import FilePreview from '@beisen-phoenix/file-list';

const App: React.FunctionComponent<any> = props => {
  let [files, setFiles] = useState<UploadFileType[]>([]);
  const handleError = err => {
    console.log(err, 'error');
  };

  const handleChange = (d: UploadFileType[]) => {
    setFiles(d);
  };

  const handleDelete = (data: UploadFileType) => {
    let idx = files.findIndex(item => item.id === data.id);
    if (idx !== -1) {
      setFiles([...files.slice(0, idx), ...files.slice(idx + 1)]);
    }
  };

  return (
    <div>
      <FilePreview files={files} edit={true} onDelete={handleDelete} />
      <Upload
        multiple={true}
        onError={handleError}
        limit={10}
        onChange={handleChange}
        files={files}
      >
        <button>上传</button>
      </Upload>
    </div>
  );
};

export default App;