Skip to content

插件系统

概述

file-ud.js 提供了强大的插件系统,允许你通过非侵入式的方式扩展上传功能。所有插件都实现 IUDPlugin 接口,可以在不修改核心代码的情况下添加新功能。

插件架构

file-ud.js 的插件架构分为三层:

file-ud.js 插件分层架构图

层级所在包职责
核心传输层@file-ud.js/core管理 Uploader / Downloader、文件队列、进度、事件、暂停、恢复、取消等核心能力
插件协议层IUDPlugin / PluginContext定义插件名称、优先级、安装、文件选择、传输前、进度、成功、失败、销毁等生命周期
插件实现层@file-ud.js/plugins提供上传插件、下载插件、通用插件,也支持业务方自定义插件

整体执行链路:

text
FileUD.createUploader() / FileUD.createDownloader()

transfer.use(plugin)

plugin.install()

onFileSelect / beforeTransfer

文件上传或下载

onProgress

onSuccess / onError

destroy()

包入口设计

插件按使用场景拆分子入口,避免上传项目误引下载插件,也方便打包工具做 Tree Shaking。

场景导入路径适合放置的插件
上传专用@file-ud.js/plugins/uploader文件验证、图片压缩、水印、上传前处理
下载专用@file-ud.js/plugins/downloader下载重试、下载限速、保存策略
通用能力@file-ud.js/plugins/retry上传和下载都能使用的重试能力
基类 / 类型@file-ud.js/pluginsBasePlugin、公共插件基础设施

插件上下文

插件钩子会接收 PluginContext,用于读取当前传输实例和跨插件共享数据:

字段说明
transfer当前 UploaderDownloader 实例
file当前正在处理的文件对象
config当前传输配置
shared插件间共享的 Map,适合传递临时处理结果

插件应该优先通过上下文和公开 API 工作,避免直接修改内部私有状态。需要改变文件内容时,建议在 onFileSelect 中返回新的文件对象;需要拦截上传或下载时,建议在 beforeTransfer 中返回 false

设计理念

非侵入式扩展

  • 零核心代码修改:所有功能通过插件实现
  • 向后兼容:不影响现有功能和 API
  • 可选启用:用户可以选择性使用插件

优先级机制

每个插件可以设置 priority(数字越小越先执行):

优先级区间用途示例
0 - 5验证类插件FileValidatorPlugin
10 - 20处理类插件CompressImagePlugin、SmartRetryPlugin
20 - 50辅助类插件WatermarkPlugin

安装

bash
# npm
npm install @file-ud.js/plugins

# pnpm
pnpm add @file-ud.js/plugins

# yarn
yarn add @file-ud.js/plugins

# bun
bun add @file-ud.js/plugins

快速使用

ts
import { FileUD } from "@file-ud.js/core";
import {
  FileValidatorPlugin,
  CompressImagePlugin,
} from "@file-ud.js/plugins/uploader";
import { SmartRetryPlugin } from "@file-ud.js/plugins/retry";

const uploader = FileUD.createUploader("myUploader", {
  action: "/api/upload",
});

// 注册多个插件
uploader.use([
  new FileValidatorPlugin({ maxSize: 10 * 1024 * 1024 }),
  new CompressImagePlugin({ quality: 0.8 }),
  new SmartRetryPlugin({ maxRetries: 3 }),
]);

推荐导入路径:

场景导入路径
上传插件@file-ud.js/plugins/uploader
下载插件@file-ud.js/plugins/downloader
通用插件@file-ud.js/plugins/retry
自定义插件基类@file-ud.js/plugins

插件管理

注册实例插件

use() 只影响当前 uploaderdownloader 实例。可以传入单个插件,也可以传入插件数组:

ts
uploader.use(new FileValidatorPlugin({ maxSize: 10 * 1024 * 1024 }));

uploader.use([
  new FileValidatorPlugin({ maxSize: 10 * 1024 * 1024 }),
  new CompressImagePlugin({ quality: 0.8 }),
  new SmartRetryPlugin({ maxRetries: 3 }),
]);

同名插件重复注册时会被跳过,插件会按 priority 从小到大执行。

卸载插件

unuse(name) 会从当前实例移除指定插件,并调用插件的 destroy() 钩子:

ts
uploader.unuse("compress-image-plugin");
uploader.unuse("SmartRetryPlugin");

卸载只影响当前实例,不会修改全局默认插件配置。

查看插件

ts
const retryPlugin = uploader.getPlugin("SmartRetryPlugin");
const plugins = uploader.getPlugin();

传入插件名称时返回单个插件;不传名称时返回当前实例的插件列表。

设置全局默认插件

如果项目里每个上传器都需要同一组插件,可以在创建上传器之前设置全局默认插件:

ts
import { Uploader, Downloader } from "@file-ud.js/core";
import { FileValidatorPlugin } from "@file-ud.js/plugins/uploader";
import { SmartRetryPlugin } from "@file-ud.js/plugins/retry";

Uploader.setDefaultPlugins([
  new FileValidatorPlugin({ maxSize: 10 * 1024 * 1024 }),
  new SmartRetryPlugin({ maxRetries: 3 }),
]);

Downloader.setDefaultPlugins([
  new SmartRetryPlugin({ maxRetries: 3 }),
]);

const uploader = FileUD.createUploader("avatarUploader", {
  action: "/api/upload",
});

全局默认插件只会影响之后创建的实例;已经创建好的实例不会自动追加这些插件。需要清空默认插件时传入空数组:

ts
Uploader.setDefaultPlugins([]);
Downloader.setDefaultPlugins([]);

执行顺序

插件按 priority 从小到大依次执行:

文件选择

FileValidatorPlugin (priority: 0)    →  验证文件合法性

CompressImagePlugin  (priority: 10)  →  压缩图片

WatermarkPlugin      (priority: 20)  →  添加水印

上传开始

SmartRetryPlugin     (priority: 10)  →  失败时自动重试

上传完成

内置插件

插件优先级说明
文件验证0验证文件大小、类型、空文件检测
图片压缩10智能压缩、尺寸调整、格式转换
水印20文字/图片水印,5 个预设位置
智能重试10三种重试策略,智能错误过滤

开发自定义插件

所有插件必须实现 IUDPlugin 接口,推荐继承 BasePlugin 基类:

ts
import { BasePlugin } from "@file-ud.js/plugins";
import type { UploadFile, PluginContext } from "@file-ud.js/core/types";

class MyPlugin extends BasePlugin {
  name = "my-plugin";
  priority = 50;

  async onFileSelect(
    file: UploadFile,
    context: PluginContext
  ): Promise<UploadFile> {
    console.log("文件已选择:", file.fileName);
    return file;
  }
}

uploader.use(new MyPlugin());

完整开发指南参见各内置插件的源码实现。

基于 MIT 协议发布