早期项目我采用的是百度 Webuploader,目前该组件已经很久没有更新了。
最近还看了 filepond 效果不错,插件丰富并支持 Vuejs,不过样式封装的太紧密可定制性稍差。
下面要介绍的是目前项目中使用的 FileAPI,它和 Webuploader 一样,在不支持 HTML5 的环境下采用 flash 技术(不考虑,HTML5 已经是大势所趋)。
同时还包含预览、裁剪、缩放、旋转、水印等功能和 filepond 的插件比起来也不逊色。
FileAPI 只提供 API 操作方法,没有提供 UI 部分的实现,在基于 Vuejs 的项目中使用再合适不过,前端部分由 Vue 实现完成,具体操作交由 FileAPI。
遗憾的是在 Github 上拥有 3.4k★ 的项目没有提供 TypeScript 声明文件,开发中 IDE 没有智能提示,附上的声明文件是根据 FileAPI 官方文档编写的。
/**********************************
** FileAPI 声明文件
** 作者:DAOSR 创建日期:2019-08-10
**********************************/
declare namespace FileAPI {
type ResizeType = 'min' | 'max' | 'preview';
type ProgressEventType = 'load' | 'error' | 'progress';
type ImageTransformType = 'image/jpeg' | 'image/png';
interface IFile {
name: string;
type: string;
size: number;
}
interface IProgressEvent {
type: ProgressEventType,
loaded: number;
total: number;
result: any;
}
interface IEvent {
on(el: HTMLElement, events: string, handler: (event: Event) => void | Function): void;
off(el: HTMLElement, events: string, handler: (event: Event) => void | Function): void;
one(el: HTMLElement, events: string, handler: (event: Event) => void | Function): void;
}
interface Image {
crop(width: number, height: number): Image;
crop(x: number, y: number, width: number, height: number): Image;
resize(width: number, height: number, type?: ResizeType): Image;
preview(width: number, height?: number): Image;
rotate(deg: number | 'auto'): Image;
filter(callback: void): Image;
filter(name: string): Image;
overlay(images: []): Image;
get(fn: (error: string, image: HTMLCanvasElement) => void): Image;
}
interface ImageTransform {
width?: number;
height?: number;
maxWidth?: number;
maxHeight?: number;
preview?: boolean;
type?: ImageTransformType
}
interface IOptions {
url: string;
files: any;
data?: any;
headers?: any;
chunkSize?: number;
chunkRetry?: number;
imageTransform?: boolean | ImageTransform;
imageOriginal?: boolean;
imageAutoOrientation?: boolean;
prepare?: (file: IFile, options: IOptions) => void;
upload?: (xhr: XMLHttpRequest, options: IOptions) => void;
fileupload?: (file: any, xhr: XMLHttpRequest, options: IOptions) => void;
progress?: (event: IProgressEvent, file: IFile, xhr: XMLHttpRequest, options: IOptions) => void;
fileprogress?: (event: IProgressEvent, file: IFile, xhr: XMLHttpRequest, options: IOptions) => void;
complete?: (error: string, xhr: XMLHttpRequest, file: IFile, options: IOptions) => void;
filecomplete?: (error: string, xhr: XMLHttpRequest, file: IFile, options: IOptions) => void;
}
interface Instance {
event: IEvent;
Image(file: IFile): Image;
getFiles(input: HTMLInputElement | Event): IFile[];
getInfo(file: any, callback: (error: string, info: any) => void): void;
filterFiles(files: IFile[], filter: (file: IFile, info: any) => boolean, callback: (list: IFile[], other: IFile[]) => void): void;
getDropFiles(event: any, callback: (files: IFile[]) => void): void;
upload(opts: IOptions): XMLHttpRequest;
addInfoReader(mime: RegExp, handler: (file: IFile, callback: void) => void): void;
readAsDataURL(file: IFile, callback: (event: IProgressEvent) => void): void;
readAsBinaryString(file: IFile, callback: (event: IProgressEvent) => void): void;
readAsText(file: IFile, callback: (event: IProgressEvent) => void): void;
readAsText(file: IFile, encoding: string, callback: (event: IProgressEvent) => void): void;
}
}