上传逻辑
开发者未提供任何描述性文档
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;