Skip to content

Uploader 上传

Uploader 组件用于图片或文件的上传。

详情列表

list-type属性设置为details,显示文件详情列表。

图片列表

list-type属性设置为image-card,显示图片列表。

自定义文件获取方式

默认情况下,用户点击上传按钮后通过 h5 选择文件。通过file-picker-items属性可以传入一个文件选取方式列表,为用户提供多种文件选取方式。

手动上传

auto-upload属性设置为false,选择文件后不会立即上传,调用组件的uploadFiles方法后才会开始上传。

自定义上传方法

通过传入actionmethoddata等属性可以使用组件本身提供的上传功能,也可以通过custom-upload-method属性传入自定义的上传方法,自己实现将文件上传到后端的方法。

上传前校验

组件本身不会向用户提示上传前校验所发现的问题,可以通过on-validate回调方法来获取上传前校验的结果并向用户进行提示。

类型

typescript
/**
 * 文件读取的结果类型
 * @description 值为`file`时返回文件的`File`对象,值为`dataUrl`时返回文件对应的base64编码
 */
export type FileReadType = 'file' | 'dataUrl';

export type HttpMethod =
  | 'POST'
  | 'GET'
  | 'PUT'
  | 'OPTION'
  | 'PATCH'
  | 'post'
  | 'get'
  | 'put'
  | 'option'
  | 'patch';

/**
 * 文件条目
 */
export interface FileItem {
  /** 文件名称 */
  name?: string;

  /** 原始文件对象 */
  rawFile?: File;

  /** base64格式的文件内容 */
  dataUrl?: string;

  /** 原始文件的MIME类型 */
  type?: string;

  /** 文件的大小 (Bytes) */
  size?: number;

  /** 上次修改时间 */
  lastModified?: number;
}

/**
 * 上传文件条目
 */
export interface UploadFileItem extends FileItem {
  /**
   * 文件名称
   * @description 根据文件的后缀名判断文件类型
   */
  name?: string;

  /** 文件的预览图片的地址 */
  thumbnailUrl?: string;

  /** 文件的下载地址 */
  url?: string;

  /** 文件的上传时间 */
  uploadTime?: string;

  /** 文件的大小 (Bytes) */
  size?: number;

  /**
   * 文件上传状态
   * @description 上传成功、上传失败、上传中、等待上传
   */
  status?: 'success' | 'fail' | 'progress' | 'waiting';

  /**
   * 文件上传进度
   * @description 上传进度百分比,[0, 100]
   */
  percent?: number;

  /**
   * 文件ID
   * @description 用于在文件名称重复时唯一标识一个文件,允许为空
   */
  id?: string;

  /** 用户自定义的上下文数据 */
  [key: string]: any;
}

/**
 * 文件上传进度变更信息
 */
export interface UploadProgressContext {
  /** 上传进度类型 */
  type: 'real' | 'mock';

  /**
   * 相关文件
   * @description 如果单请求上传多个文件,则长度大于一
   */
  files: UploadFileItem[];

  /** 百分比进度值 */
  percent: number;

  [key: string]: any;
}

/**
 * 上传请求响应数据
 * @description 后端上传接口响应的数据
 */
export interface UploadResponseData {
  /**
   * 错误信息
   * @description 如果本字段非空,则认为文件上传失败了
   */
  error?: string;

  /**
   * 上传后的文件访问地址
   * @description 将被赋值给对应文件的`url`字段(单请求上传多个文件`singleRequestUpload=true`时无效)
   */
  url?: string;

  /**
   * 上传后的文件缩略图地址
   * @description 将被赋值给对应文件的`thumbnailUrl`字段(单请求上传多个文件`singleRequestUpload=true`时无效)
   */
  thumbnailUrl?: string;

  [key: string]: any;
}

/**
 * 单个文件上传结果的上下文
 */
export interface UploadResponseContext {
  /**
   * 上传的文件
   */
  file: UploadFileItem;

  /**
   * 是否上传成功
   */
  success: boolean;

  /**
   * 上传请求的响应数据
   * @description 如果是单请求上传多个文件的模式(`singleRequestUpload=true`时),则该字段为空
   */
  responseData?: UploadResponseData;
}

/**
 * 自定义文件上传上下文
 * @description 当用户自定义文件上传方法时,可以通过本上下文中的回调方法通知文件的上传状态
 */
export interface CustomUploadFileContext {
  /** 待上传的文件 */
  file: UploadFileItem;

  /**
   * 更新上传进度回调
   * @description 用于更新当前文件的上传进度
   */
  onProgress: (e: { percent: number } & Record<string, any>) => void;

  /**
   * 上传成功回调
   * @description 文件上传成功后回调,允许将请求响应数据作为参数
   */
  onSuccess: (e?: UploadResponseData) => void;

  /**
   * 上传失败回调
   * @description 文件上传失败后回调,允许将请求响应数据作为参数
   */
  onFail: (e?: UploadResponseData) => void;
}

export interface UploadResult {
  /**
   * 单请求多文件上传的响应数据
   * @description 上传请求的响应数据,仅当单请求上传多个文件`singleRequestUpload=true`时非空
   */
  responseData?: UploadResponseData;

  /**
   * 上传成功的文件及其响应数据
   * @description 如果没有文件上传成功,则为空
   */
  successItems?: UploadResponseContext[];

  /**
   * 上传失败的文件及其响应数据
   * @description 如果没有文件上传失败,则为空
   */
  failedItems?: UploadResponseContext[];
}

/**
 * 内建的列表样式
 * @description `文件详情列表`或者`图片列表`
 */
export type UploaderListType = 'details' | 'image-card';

/**
 * 文件选取参数
 */
export interface FilePickerOption {
  /**
   * 接受上传的文件类型
   * @description 默认不限制
   */
  accept?: string;

  /**
   * 是否启用文件多选
   * @description 是否允许用户一次选择多个文件
   */
  multiple?: boolean;

  /**
   * 文件读取的结果类型
   * @description 用户选择的文件将被转化为本字段所指定的格式
   */
  fileReadType?: FileReadType;

  /** 单个文件的大小限制 (Bytes) */
  maxSize?: number;

  /**
   * 最大文件数量
   * @description 最多可以上传多少个文件
   */
  maxCount?: number;

  /**
   * 已上传文件的数量
   * @description 已经上传了多少个文件,用`maxCount - uploadedFileCount`可以得到还能上传的最大文件数量
   */
  uploadedFileCount?: number;

  [key: string]: any;
}

/**
 * 上传组件上下文
 * @description 组件的相关属性,只读
 */
export interface UploaderContext extends FilePickerOption {
  /** 文件列表的内建样式 */
  listType?: UploaderListType;

  /** 组件是否处于只读状态 */
  readonly?: boolean;

  /** 组件是否处于禁用状态 */
  disabled?: boolean;

  /** 接受上传的文件类型 */
  accept?: string;

  /** 是否启用文件多选 */
  multiple?: boolean;

  /** 文件读取的结果类型 */
  fileReadType?: FileReadType;

  /** 单个文件的大小限制 (Bytes) */
  maxSize?: number;

  /** 最大文件数量 */
  maxCount?: number;

  /** 已上传文件的数量 */
  uploadedFileCount?: number;

  /** 当前显示的文件列表 */
  displayFiles?: UploadFileItem[];
}

/**
 * 自定义文件获取方式
 */
export interface FilePickerItem {
  /**
   * 方式编号
   * @description 唯一标识,不可重复
   */
  key: string;

  /**
   * 显示的名称
   */
  name?: string | ((context: UploaderContext, customOptions: Record<string, any>) => string);

  /**
   * 文件获取的实现方法
   * @description 当用户选择本方式后,将调用本方法来获取文件。
   * 如果`handler`字段为空,且不存在默认配置,则用户选择此方式后将通过h5方式选取文件。
   */
  handler?: (context: UploaderContext, customOptions: Record<string, any>) => Promise<FileItem[]>;

  /**
   * 是否显示
   * @description 如果本方式仅部分平台支持,则应该根据平台的能力决定是否显示本方式
   */
  visible?: boolean | ((context: UploaderContext, customOptions: Record<string, any>) => boolean);

  /**
   * 提示文本
   * @description 显示在名称下方的一行文本
   */
  tip?: string | ((context: UploaderContext, customOptions: Record<string, any>) => string);

  /**
   * 自定义选项
   * @description 一般不需要配置
   */
  customOptions?: Record<string, any>;
}

/** 文件条目的上下文数据 */
export interface FileItemContext {
  /** 被选中的文件 */
  file: UploadFileItem;

  /** 被选中文件在文件列表中的下标 */
  index: number;

  /** 文件列表 */
  fileList: UploadFileItem[];

  /** 上传组件的上下文 */
  uploaderContext: UploaderContext;
}

/**
 * 文件条目的上下文菜单项
 */
export interface FileContextMenuItem {
  /**
   * 选项编号
   * @description
   * 唯一标识,不可重复。
   * 1. 当`key='preview'`时,点击选项将触发预览,组件将执行默认的预览操作(可通过`preventDefaultPreview`禁用)并抛出预览事件;
   * 2. 当`key='delete'`时,点击选项将触发删除,组件将向外抛出删除事件;
   * 3. 当`key`等于其它值时,没有默认行为,需要用户通过`handler`方法自定义实现。
   */
  key: 'preview' | 'delete' | string;

  /**
   * 显示的名称
   */
  name?: string | ((context: FileItemContext, customOptions: Record<string, any>) => string);

  /**
   * 选项行为的实现方法
   * @description 当用户选择本选项后,将调用本方法
   */
  handler?: (context: FileItemContext, customOptions: Record<string, any>) => boolean;

  /**
   * 是否显示
   * @description 默认显示,可以用来隐藏不被支持的选项
   */
  visible?: boolean | ((context: FileItemContext, customOptions: Record<string, any>) => boolean);

  /**
   * 是否禁用
   * @description 默认不禁用,当回调方法返回`true`或非空字符串时禁用,返回的字符串将被作为提示文本显示在名称下方,具有比`tip`更高的优先级
   */
  disabled?:
    | boolean
    | ((context: FileItemContext, customOptions: Record<string, any>) => boolean | string);

  /**
   * 提示文本
   * @description 显示在名称下方的一行文本
   */
  tip?: string | ((context: FileItemContext, customOptions: Record<string, any>) => string);

  /**
   * 自定义选项
   * @description 一般不需要配置
   */
  customOptions?: Record<string, any>;
}

/**
 * 弹层的类型
 * @description 文件选取动作列表、文件条目上下文菜单的动作列表、文件条目上下文菜单的`tooltip`
 */
export enum UploaderPopupType {
  FilePickerActionSheet = 'FilePickerActionSheet',
  ContextMenuActionSheet = 'ContextMenuActionSheet',
  ContextMenuTooltip = 'ContextMenuTooltip'
}

/**
 * 上传文件列表变更上下文
 */
export interface FileListUpdateContext {
  /**
   * 变更来源
   * @description
   * 1. `add` 上传后新增文件
   * 2. `delete` 点击删除按钮或者上下文菜单中的删除选项后删除文件
   */
  trigger: 'add' | 'delete';
}

/** 文件上传前校验参数 */
export interface BeforeUploadValidationParam {
  /** 待上传的(需要校验的)文件列表 */
  files: FileItem[];
  /** 已上传的文件列表 */
  uploadedFiles?: UploadFileItem[];
  /** 文件数量上限 */
  maxCount?: number;
  /** 单个文件的大小上限 */
  maxSize?: number;
  /** 是否允许重名文件 */
  allowDuplicateFile?: boolean;
  /** 单个文件上传前回调 */
  beforeUpload?: (file: UploadFileItem, context: any) => boolean | Promise<boolean>;
  /** 上下文 */
  context?: any;
}

/** 文件条目长按事件默认行为 */
export enum FileItemLongPressAction {
  /** 不进行默认处理 */
  None = 'None',

  /** 通过下方弹出的动作列表显示自定义的上下文菜单 */
  ShowMenu = 'ShowMenu',

  /** 通过`Tooltip`组件显示自定义的上下文菜单 */
  ShowMenuInTooltip = 'ShowMenuInTooltip'
}

/** 校验发现问题的类型 */
export enum FileValidationProblemType {
  SingleFileOverSizeLimit = 'SingleFileOverSizeLimit',
  FileListOverLengthLimit = 'FileListOverLengthLimit',
  DuplicateFileNames = 'DuplicateFileNames',
  BeforeUploadCallback = 'BeforeUploadCallback'
}

/** 校验发现的问题 */
export interface FileValidationProblem {
  /** 问题类型 */
  type: FileValidationProblemType;

  /**
   * 相关的文件列表
   * @description
   * 1. 当`type="SingleFileOverSizeLimit"`时,是本次所选文件中所有超过单文件大小上限的文件;
   * 2. 当`type="FileListOverLengthLimit"`时,是本次所选的所有文件;
   * 3. 当`type="DuplicateFileNames"`时,是本次所选的文件中所有重名的文件;
   * 4. 当`type="BeforeUploadCallback"`时,是本次所选的文件中所有未通过`beforeUpload`自定义校验的文件。
   */
  files: UploadFileItem[];
}

/** 文件上传前校验结果 */
export interface BeforeUploadValidationResult {
  /** 通过校验的文件列表 */
  validFiles: UploadFileItem[];

  /** 检测到的问题列表 */
  problems?: FileValidationProblem[];

  /**
   * 校验参数
   * @description 包含本次校验的上下文参数,禁止修改
   */
  validationParam: BeforeUploadValidationParam;
}

属性

属性名类型默认值说明
filesArray as UploadFileItem[][]已上传文件列表,支持语法糖v-model:files
readonlybooleanfalse是否只读,只读状态下将隐藏上传按钮和删除按钮
disabledbooleanfalse是否禁用,禁用状态下将禁用上传按钮和删除按钮,优先级低于readonly属性
listTypestring as UploaderListType'details'文件列表的内建样式,支持两种基础样式:details(文件详情列表)、image-card(图片列表)
uploadButtonPosition'start' | 'end''end'上传按钮的位置,默认在图片列表的右侧或文件详情列表的下方
imagePropsObject{}图片属性,透传给缩略图的图片相关属性
fileReadTypestring as FileReadType'file'文件读取的结果类型,指定用户所选文件是以File对象的形式返回,还是以 base64 格式的字符串的形式返回
filePickerItemsArray as FilePickerItem[]--自定义的文件获取方式列表,如果为空,则用户点击上传按钮后通过 h5 选择文件,如果非空,则通过列表中定义的方式获取文件
contextMenuItemsArray as FileContextMenuItem[][{ key: 'preview' }, { key: 'delete' }]自定义的上下文菜单。当listType='details'时,点击更多按钮,弹出上下文菜单。传入longPressAction属性,可以使得长按文件条目时弹出上下文菜单。
preventDefaultPreviewbooleanfalse阻止默认的预览行为,默认情况下,如果点击了图片类型的文件条目,则进行预览,其它类型的文件没有默认的预览。可以将本属性置为true,然后通过文件条目点击事件或回调方法实现自定义的文件预览。
getThumbnailUrl(file: UploadFileItem) => string | Promise<string>--获取文件的预览图片地址,用户选择文件后,被选择的文件将被加入到文件列表中,此时文件的预览图地址可以根据本回调方法指定
useOriginalImageAsThumbnailbooleantrue是否将原图作为缩略图,如果文件是图片类型,则直接将之作为缩略图显示出来,不再调用getThumbnailUrl方法
acceptstring--接受上传的文件类型,仅影响默认的文件获取方式,自定义的文件获取方式可以读取该属性,但是不一定受约束
multiplebooleantrue是否启用文件多选,仅影响默认的文件获取方式,自定义的文件获取方式可以读取该属性,但是不一定受约束
maxCountnumber-1文件数量上限,值小于等于 0 则不限制
maxSizenumber-1单个文件的大小上限 (Bytes),值小于等于 0 则不限制
allowDuplicateFilebooleantrue是否允许上传同名文件,如果值为false,则过滤掉被选择的重名文件
beforeUpload(file: UploadFileItem, context: UploaderContext) => boolean | Promise<boolean>--单文件上传前回调,如果返回false则将文件过滤掉
onValidate(result: BeforeUploadValidationResult) => boolean | Promise<boolean>--校验后回调,校验结果中包含通过校验的文件列表、校验时发现的问题列表,无论是否存在文件未通过校验都将触发该回调或事件。如果回调方法返回true则继续处理通过校验的文件,如果返回false则放弃所有文件。
autoUploadbooleantrue是否在选择文件后自动上传,默认自动上传,如果手动上传,则文件被选中后处于等待状态,调用组件的上传方法后上传
actionstring''上传请求的地址,action非空且customUploadMethod为空时,启用内置的文件上传方式
methodstring as HttpMethod'POST'HTTP 的请求方法,随action生效,可选值:POST/GET/PUT/OPTION/PATCH/post/get/put/option/patch
namestring'file'文件在上传请求数据中的字段名,随action生效,指定文件在请求数据中的字段名。如果fileReadType的值为file(默认)则文件作为File对象上传,如果fileReadType的值为dataUrl则文件作为 base64 格式的字符串上传。如果singleRequestUpload=true且用户选择了多个文件,所有文件将使用相同的字段名。如果默认的规则不能满足业务需求,请使用formatRequestData属性来自定义请求数据,或者通过customUploadMethod属性自定义上传方法。
dataObject--上传请求所需的额外字段,随action生效,用于添加文件字段之外的其它字段。如果默认的规则不能满足业务需求,请使用formatRequestData属性来自定义请求数据。
headersObject--自定义 HTTP 请求头,随action生效
withCredentialsbooleanfalse是否携带 cookie,随action生效,默认不携带
timeoutnumber--上传请求的超时时间,随action生效,单位:毫秒,默认不设置
formatRequestData(files: UploadFileItem[], data: { [key: string]: any }) => { [key: string]: any }--自定义上传请求的参数,随action生效,用于自定义上传请求参数,本方法非空时,namedata字段均失效
formatResponseData(response: any, uploadFiles: UploadFileItem[]) => UploadResponseData--格式化上传请求的响应数据,随action生效,用于将上传请求返回的数据格式化为规定的结构。如果请求失败或者error字段非空,则认为文件上传失败。如果请求成功并且error字段为空,则认为文件上传成功。如果未设置本回调方法,则根据请求是否成功以及请求的原始响应数据中的error字段是否为空判断文件是否上传成功。如果singleRequestUpload=true单次请求上传多个文件,则所有上传的文件只能一起成功或者一起失败。如果既要单次请求上传多个文件,又要单独记录每个文件的上传成功和失败状态,请通过自定义上传方法customUploadMethod实现。
customUploadMethod(uploadContext: CustomUploadFileContext | CustomUploadFileContext[]) => void--自定义上传方法,如果非空,则使用本方法进行自定义上传,action等内置上传的相关字段均失效。本属性受singleRequestUpload字段影响:如果singleRequestUpload=true则用户选择多个文件时只会调用一次customUploadMethod,否则将调用多次。
singleRequestUploadbooleanfalse单次请求上传所有文件,如果有多个文件需要上传,若启用该属性则通过一个请求上传所有文件,否则每个文件发一次请求
useMockProgressbooleantrue是否模拟上传进度
onOneFileSuccess(context: UploadResponseContext) => void--单文件上传成功回调方法,每个文件上传成功后都会调用该方法(singleRequestUpload=true时无效)
onOneFileFail(context: UploadResponseContext) => void--单文件上传失败回调方法,每个文件上传失败后都会调用该方法(singleRequestUpload=true时无效)
onProgress(context: UploadProgressContext) => void--上传进度变化回调方法,当文件的上传进度发生变化时回调该方法
onUploadFinish(result: UploadResult) => void--上传完成后回调方法,将用户单次选择的文件全部上传结束后回调
onFileItemClick(payload: { context: FileItemContext; event: MouseEvent }) => void--文件条目点击事件回调方法,当文件条目被点击时回调该方法,注意:点击文件条目上的删除按钮、菜单按钮不会回调该方法
longPressActionstring as FileItemLongPressAction'None'文件条目长按事件默认行为,允许定制文件条目被长按后的具体行为
longPressDelaynumber600触发文件条目长按事件默认行为所需要长按的最短时间,单位:ms,默认:600
onLongPress(payload: { context: FileItemContext; event: TouchEvent }) => void--文件条目长按事件回调方法,长按文件条目后回调本方法,与longPressAction属性的取值无关
onDelete(payload: { context: FileItemContext; event?: MouseEvent }) => void--删除回调方法,当用户点击文件条目上的删除按钮时回调该方法
onPopupOpen(payload: { close: () => void; type: UploaderPopupType; uid: string }) => void--打开弹层时回调方法,调用close方法可以主动关闭对应的弹层,且不会触发关闭弹层事件或回调。结合onPopupOpenonPopupClose,可以实现对弹层的原生返回处理。
onPopupClose(payload: { type: UploaderPopupType; uid: string }) => void--关闭弹层时回调方法

事件

事件名类型说明
validateEventEmitter<BeforeUploadValidationResult>上传前校验事件
progressEventEmitter<UploadProgressContext>上传进度变化事件
oneFileSuccessEventEmitter<UploadResponseContext>单文件上传成功事件
oneFileFailEventEmitter<UploadResponseContext>单文件上传失败事件
uploadFinishEventEmitter<UploadResult>上传完成后事件
fileItemClickEventEmitter<{ context: FileItemContext; event: MouseEvent }>文件条目点击事件
deleteEventEmitter<{ context: FileItemContext; event?: MouseEvent }>文件条目删除事件
longPressEventEmitter<{ context: FileItemContext; event: TouchEvent }>文件条目长按事件
popupOpenEventEmitter<{ close: () => void; type: UploaderPopupType; uid: string }>打开弹层事件
popupCloseEventEmitter<{ type: UploaderPopupType; uid: string }>关闭弹层事件

插槽

名称说明
uploadButtonContent上传按钮内容
uploadButton上传按钮,优先级高于uploadButtonContent
default上传按钮,同uploadButton

组件实例

名称类型说明
displayFilesRef<UploadFileItem[]>显示的文件列表
toUploadFilesRef<UploadFileItem[]>待上传的文件列表
uploadingReadonly<Ref<boolean>>是否正在上传
uploaderContextUploaderContext组件上下文
triggerUpload() => void触发上传操作,选择文件并上传
uploadFiles(files?: UploadFileItem[]) => void上传文件,手动上传模式下,可以通过调用本方法将准备上传状态的文件上传

CSS 变量

名称默认值说明
--fm-uploader-gap12px--
--fm-uploader-gap-horizontalvar(--fm-uploader-gap)--
--fm-uploader-gap-verticalvar(--fm-uploader-gap)--
--fm-uploader-item-box-shadowunset--
--fm-uploader-image-card-item-background#f2f2f2--
--fm-uploader-image-card-mask-backgroundrgba(0, 0, 0, 0.4)--
--fm-uploader-thumbnail-widthunset--
--fm-uploader-thumbnail-heightunset--
--fm-uploader-thumbnail-border-radius6px--
--fm-uploader-add-btn-sizeunset--
--fm-uploader-add-btn-widthvar(--fm-uploader-add-btn-size)--
--fm-uploader-add-btn-heightvar(--fm-uploader-add-btn-size)--
--fm-uploader-add-btn-backgroundunset--
--fm-uploader-add-btn-border-radiusunset--
--fm-uploader-add-btn-box-shadowunset--
--fm-uploader-add-btn-icon-sizeunset--
--fm-uploader-add-btn-icon-color#929292--
--fm-uploader-del-btn-size16px--
--fm-uploader-del-btn-background#666666--