上传逻辑
开发者未提供任何描述性文档
Storybook
SUCCESS0 DEPENDENCIES0

上传组件

souce code

说明

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

upload 目前有四个相关组件

为什么使用受控组件

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

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

导出说明

默认导出为 Upload 只包含上传逻辑,需要配合 children 属性,包裹元素使用 还导出了 UploadDnd 支持拖拽上传样式,可以查看示例

API

上传逻辑和上传样式的公共 api

参数 说明 类型 默认值 是否必传
url 上传接口地址(只支持 post) string 或 ((f: any, opt?: any) => string) 无 yes
multiple 是否允许多选 boolean true no
maxSize 文件体积限制(单位M) number 无 no
maxFiles 文件个数限制 number 无 no
onError 发生错误回调 (err: any) => void 无 yes
files 文件列表 IUploadFileType[] 无 true
onChange 单个文件上传完成时的回调 (f: IUploadFileType[]) => void; 无 true
onEachComplete 文件状态发生变化时的回调 (data: Partial) => void; 无 否
accept 接受的文件类型格式 string 或者 string[] 无 否
parseResponse 格式化上传接口返回的数据 IParseResponse 无 true
validator 自定义的文件验证方法,在选择文件后调用,可以按照自己的需求过滤 (file: File[]) => File[] 或者 Promise<File[]> 无 否
chunkUploadEnabled 是否开启分片上传(注意,还需要后端接口支持分片上传) boolean | ((file: File) => boolean) 否
chunkSize 分片大小 number 5 * 1024 * 1024 否
parallelUploadLimit 并行上传数, 为1时即可实现串行上传 number 5 否
prepareChunkUpload 分片上传前置准备逻辑,如果开启分片上传,需要先从服务端获取fileId,后续分片上传会带上该id (file: File) => Promise<{ fileId: string; [key: string]: any }> 无 开启分片上传时必传
disabled 是否禁用 boolean false 否

UploadDnd 特有 api

参数 说明 类型 默认值 是否必传
width 宽度 string 无 否
height 高度 string 无 否
error 是否报错 boolean false 否
size 尺寸(分为大号和小号) EDndSize EDndSize.small 否
text 显示主文本 ReactNode 无 否
subText 副标题 (仅 size=EDndSize.big)时有效 ReactNode 无 否
lang 当前语言环境(zh_CN,en_US,zh_TW) string zh_CN 否
translation 自定义语言包,详情见下方 object - 否

[5.0.41] 2021-03-08

  • fix 增加参数:customComposeFiles;支持用户自定义文件对比规则。

[version]

  • feat 添加参数lang,设置当前语言环境

translation

translation: {
  upload: '将文件拖至此处,或点此上传'
}
  • files: UploadFileType[] 文件列表
  • onChange: (files: UploadFileType[]) => void 当文件状态发生变化的时候的回调

期中 UploadFileType 的类型定义为

interface IParseResponse {
  (data: any): Partial<IUploadFileType>;
}
enum EDndSize {
  big = "big",
  small = "small"
}
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;