文件分片上传 Filepond

应用场景

功能定位

FilePond 是一个灵活的文件上传库,可以拖入上传文件,并且会对图像进行优化以加快上传速度。让用户体验到出色、进度可见、如丝般顺畅的用户体验!能在大文件分片上传场景下,集成了上传、重传、删除等多种功能。

www.jianshu.com/p/1565067eb...

特点优势

  • 上传内容:支持目录、文件、多个文件、本地路径、远程 URL 等。
  • 文件管理:删除文件、选择文件、复制和粘贴文件、或使用 API 方式添加文件。
  • 上传方式:使用 AJAX 进行异步上传、或将文件编码为 base64 数据用表单发送、分片上传。
  • 图像优化:自动调整图像大小、裁剪和修复 EXIF 方向。
  • 响应式:可在移动和桌面设备上使用。
  • 插件:拥有多样、强大的插件,定制化不同需求

插件生态

FilePond 该库拥有多样、强大的插件部分,可以根据自己的需求选择插件组合起来使用,部分常用插件如下所示:

  • File Rename:重命名客户端上的文件
  • File Encode:将文件编码为 base64 数据
  • File size Validation:文件大小验证工具
  • File Type Validation:文件类型验证工具
  • File Metadata:限制要添加的文件类型
  • File Poster:在文件项目中显示图像
  • Image Preview:显示图像文件的预览
  • Image Edit:手动编辑图像文件
  • Image Crop:设置图像文件的裁剪比例
  • Image Resize:设置图像文件的输出尺寸
  • Image Transform:上传之前在客户端上图像变换
  • Image EXIF Orientation:提取 EXIF 方向信息
  • Image Size Validation:限制要添加的图像的尺寸
  • Image Filter:将颜色矩阵应用于图像像素

注:完整的插件列表及对应插件 API 文档链接,请查看 👇👇👇

pqina.nl/filepond/pl...

引入插件的基本步骤:

  1. 引入 CSS 文件(部分插件有 CSS 文件)
  2. 引入 JS 文件
  3. 注册插件
  4. 配置插件(部分插件需配置)

常用的插件使用方法:

  1. destroys:销毁实例
  2. find:返回附加提供的元素的实例
  3. getOptions:返回当前的配置项
  4. supported:鉴别浏览器是否支持 FilePond

生态环境

FilePond 作为一个出色的 JavaScript 库,其在不同项目框架、项目库中,有着出色且丰富的集成生态,如上图所示的 jQuery、React、Vue、Angular、Svelte 等。

我们重点关注 FilePond 本身!

filepond

名称 链接
npm www.npmjs.com/package/fil...
官网 pqina.nl/filepond/
github github.com/pqina/filep...

vue-filepond

名称 链接
npm www.npmjs.com/package/vue...
官网 pqina.nl/filepond/do...
github github.com/pqina/vue-f...

流程设计

上传基本流程

FilePond 异步上传文件,被成为 Processing: 简而言之,就是 FilePond 发送一个文件至服务端 server ,期望服务端返回一个唯一的文件 id(a unique file id)

下图详细介绍 Processing 的基本流程(以上传 my-file.png 为例)

  1. FilePondmultipart/form-data 形式,发送 POST 请求,上传文件 my-file.jpg
  2. server 将此文件保存在唯一的位置 tmp/12345/my-file.jpg
  3. servertext/plain 形式,返回给 FilePond 一个唯一位置 id 12345
  4. FilePond 把这个唯一位置 unique id 12345 ,存储至隐藏的 input 标签字段内
  5. client 用户提交包含带 unique idinput 选项的完整表单
  6. server 通过 unique id 移动 temp/12345 下的 my-file.jpg 文件,至最终位置 xxx 下,然后再移除掉原临时文件夹 tmp/12345

分片上传流程

  1. 为了以 切片(chunk) 形式上传文件(process file ),需要设置 chunkUploadstrue
  2. FilePond 会对大于 chunkSize 的文件,进行分片
  3. 对于小于 chunkSize 的文件,会被直接发送到 process 接口
  4. 若想强制所有文件都被以切片形式上传,只需设置 chunkForcetrue 即可

在 *分片上传场景(或称 Process Chunks) *下,在 接口请求中 需包含自定义 Header 如下:

Header Description
Upload-Length 被传输文件的总字节数
Upload-Name 被传输文件的名称
Upload-Offset 被传输切片的字节偏移量
Content-Type patch 请求的内容类型,设定为'application/offset+octet-stream'

简易流程

  1. FilePond 将通过发送一个 POST 请求(不带文件数据,并在请求头中携带 Upload-Length ),以开启分片上传!并期望从接口响应中拿到一个唯一的传输 id
  2. FilePond 将通过发送一个 PATCH 请求,向服务端推送一个切片。未来的每个切片推送请求,都将携带 Content-Type、Upload-Offset、Upload-Name、Upload-Length
  3. FilePond 将通过发送一个 HEAD 请求,获取哪些切片已经被上传,并期望从 响应头 中的 Upload-Offset 中,获取到下一个切片的文件偏移量

详细流程

  1. FilePondserver 请求一个唯一的传输 id(transfer id ),用来标识未来文件传输的唯一位置。这个请求默认以 POST 方法发送,并在请求头中携带要上传文件的总字节数,即 Upload-Length
  2. server 收到请求后,便会创建唯一的位置(目录)tmp/12345/ ,用于存放未来的文件切片
  3. server 将刚创建唯一位置,对应的 id 12345 ,以 text/plain 形式作为接口响应内容
  4. FilePond 拿到接口响应后,将其存储至 File Item(FilePond 对 file 的二次封装)

自此,命运的齿轮开始转动......

  1. FilePond 通过一个携带 unique id 12345PATCH 请求,开始上传第一个切片!所有切片上传的 PATCH 请求,都会在请求头中携带 Upload-Offset、Upload-Length、Upload-Name
  2. FilePond 在所有切片都被成功上传前,会依次发送切片上传请求
  3. server 在所有切片都被上传成功后,会主动根据切片,创建文件
  4. 当所有切片都被成功上传,FilePond 会将 unique id 12345 存储至 <fieldset > 标签下的 <input > 中,作为该文件的 server id(用于 revert/remove 等操作)
  5. (非必须) client 提交 FilePond 表单( 下所有的 上的 unique id)
  6. server 通过 unique id ,移动 tmp/12345/my-file.jpg 到最终的目标位置,并将删除临时文件夹 tmp/12345

如果过程中,有一个切片上传失败了!FilePond 默认会重试 3 次(chunkRetryDelays 为 500,1000,3000

若在 3 次重试,仍失败,重试的权利则交给用户

用户重试时,FilePond 会这样处理:

  1. 因为 FilePond 会记住在上传过程中,先前的 transfer id 12345 ,重试时,FilePond 会以一个 HEAD 请求开始,并在请求 URL 中,携带该 transfer id
  2. server 响应该请求时,在响应头中,携带期望的下一个切片的字节偏移量 Upload-Offset
  3. FilePond 将所有具有低于 Upload-Offset 偏移量的块标记为已完成,并从请求偏移量处,继续上传块

如下图所示:

常用 API

导出模块 Exports

我们在项目中,通过 import 导入 filepond 后,得到的是一个 完整的对象 FilePond,该对象暴露(export)了多类模块。

引入这些导出的模块,有下面的两种方式(以导入 supported 方法为例)

  1. 方式一
js 复制代码
import FilePond from 'filepond'

const supported = FilePond.supported
  1. 方式二
js 复制代码
import { supported } from 'filepond'

暴露的导出模块,常常以 方法(Methods )、枚举(Enums)的形式存在

方法 Methods

Method Description
create(element, options) 创建一个 FilePond 实例,两个入参都是可选,非必填的
destroy(element) 销毁绑定在指定元素上的 FilePond 实例
find(element) 查找绑定在指定元素上的 FilePond 实例
parse(context) 解析 class 含 .filepond 的 DOM 片段,并将其转换为 FilePond 元素
registerPlugin(plugin) 注册一个 FilePond 插件,以供后用
setOptions(options) 为 FilePond 实例,设置页面级别默认配置 options
getOptions() 返回当前默认配置 options
supported() 判断当前浏览器是否支持 FilePond
javascript 复制代码
import { supported } from 'filepond'

const can = supported() // 判断当前浏览器是否支持 FilePond

console.log(can)
typescript 复制代码
<input type="file" class="filepond" />

<script>
  FilePond.parse(document.body);
</script>

枚举 Enums

Property Description
Status 与 FilePond 的 status 属性,共同使用,决定当前 FilePond 实例的状态
FileOrigin File Itemorigin 属性,共同使用,决定 File Item 的来源
FileStatus File Itemstatus 属性,共同使用,决定 File Item 的状态
OptionTypes
yaml 复制代码
{
    EMPTY: 0,
    IDLE: 1,
    ERROR: 2,
    BUSY: 3,
    READY: 4
}
yaml 复制代码
{
    INIT: 1,
    IDLE: 2,
    PROCESSING_QUEUED: 9,
    PROCESSING: 3,
    PROCESSING_COMPLETE: 5,
    PROCESSING_ERROR: 6,
    PROCESSING_REVERT_ERROR: 10,
    LOADING: 7,
    LOAD_ERROR: 8
}
arduino 复制代码
{
    INPUT: 1, // INPUT by the user
    LIMBO: 2, // Restored from the server as a temporary file
    LOCAL: 3  // 是本地服务器文件,已上传并确认不在服务器临时上传文件夹中的文件
};

文件信息 File Item

FileFond 实例的 addFile、getFile、processFile 方法,返回的都是 FileItem 对象。

请注意:FileItem 对象,是 FilePond 内部,对文件本身的二次封装定义,携带了与 FilePond 强相关的独特属性和方法!

Getters

Property Description
id 文件的 id
serverId 文件的 server id
origin 文件的 origin,有以下几种类型:1. input (由用户添加)
  1. limbo(临时的服务器文件)
  2. local(现有的服务器文件) | | status | 文件的当前状态,由枚举 FilePond.FileStatus 来决定 | | file | 文件 File 对象 | | fileExtension | 文件的拓展类型 extension | | fileSize | 文件的大小 size | | filename | 文件的全名(含拓展类型 extension) | | filenameWithoutExtension | 不含拓展的文件名 |

Methods

Method Description
abortLoad() 中止加载该文件
abortProcessing() 中止处理该文件
getMetadata(key?) 按 key 检索保留在文件中的元数据,若没有 key,则返回完整的元数据
setMetadata(key, value) 为文件添加额外的元数据

组件实例 Instance

每个 FilePond 实例,都有一些列方法、属性、和事件,使得在项目中的集成,变得很容易

属性 Properties

A list of properties to read from and write to the current state of FilePond.

The FilePond instance exposes a set of properties that enable us to update its state.

核心属性

FilePond 模块暴露了下面的核心属性

Property Default Value Description
element null 1. FilePond 实例的根元素
  1. 无 setter | | status | 0 | 1. FilePond 实例的状态
  2. 无 setter | | name | 'filepond' | 1. [ ] 标签的 name 属性
  3. 同时也作为 输入字段名称 | | className | null | 为 FilePond 实例的根元素,添加额外的 class 类名 |
filepond 使用示例
xml 复制代码
<template>
  <input ref="vue-filepond" type="file" />
</template>

<script>
import { create } from 'filepond'
import 'filepond/dist/filepond.min.css'

export default {
  name: 'LargeFileUpload',
  mounted() {
    const el = this.$refs['vue-filepond'] // FilePond 根元素

    this.filePond = create(el, {
      name: 'File',
      credits: [],
      className: 'tf-vue-filepond-root'
    }) // FilePond 实例
  }
}
</script>
Property Default Value Description
required false 将输出字段设为必填
disabled false 将输出字段设为禁用
captureMethod null 设置 capture 属性
files A list of file locations that should be loaded Immediately 应立即加载的文件位置列表
allowRevert true 是否启用重试按钮the revert processing button ?
allowRemove true
allowProcess true
allowReorder
Server 类属性
Property Default Value Description
server null A server configuration object describing how FilePond should interact with the server.
instantUpload true 是否将文件立即上传到服务器
chunkUploads false 启用分块上传,启后会在上传前自动将文件切成 chunkSize 块
chunkForce false 对于小于设置的 chunkSize 的文件也强制使用块
chunkSize 5000000 块的大小(以字节为单位)
chunkRetryDelays 500,1000,3000 重新上传的延迟时间
Callbacks 类属性
Property Function
oninit() FilePond 实例已被创建,并已完成初始化
onwarning(error, file, status) FilePond 抛出警告
onerror(error, file, status) FilePond 抛出异常
oninitfile(file) 已创建文件的 File Item
Property Function
onaddfilestart(file) 已开始文件加载 Started file load
onaddfileprogress(file, progress) 加载文件取得进展 Made progress loading a file
onaddfile(error, file) 无报错时,表示文件已被成功加载
Hooks 类属性
Property Description
beforeDropFile(file) 拖拽文件前的钩子,返回 false 标识阻止拖拽(支持返回 boolean 或 promise)
beforeAddFile(item) 添加文件前的钩子,返回 false 表示阻止添加(支持返回 boolean 或 promise)
beforeRemoveFile(item) 删除文件前的钩子,返回 false 表示阻止删除(支持返回 boolean 或 promise)

常见问题

css 构建失败

github.com/pqina/vue-f...

相关推荐
swg32132115 小时前
Redis实现主从选举
java·前端·redis
英俊潇洒美少年15 小时前
前端核心性能指标全解(CWV三大指标+辅助指标、检测方式、优化、面试背诵)
前端
alexander06815 小时前
JavaScript 中,对象内部函数的几种等价写法,对象外部的 几种等价写法
javascript
云水一下15 小时前
Vue.js从零到精通系列(八):项目实战——构建一个完整的电商后台管理系统
前端·javascript·vue.js
Csvn15 小时前
Vue3 响应式陷阱:解构赋值后页面不动了?Proxy 的"隐形成员"在搞鬼
前端·vue.js
LAM LAB15 小时前
【Web】网页如何模拟移动端获取定位\定位模拟测试
开发语言·前端·javascript
yunceqing15 小时前
从Excel调度到TMS平台:物流软件开发避坑清单
大数据·前端·网络·人工智能·excel·推荐算法
IT_陈寒15 小时前
Redis主从切换把我坑惨了,这份血泪史你最好看看
前端·人工智能·后端
小森林之主15 小时前
JavaScript 正则表达式:从零开始的实战对比
javascript·正则表达式·前端开发·性能对比·文本处理
weixin_4713830315 小时前
Taro-04-网络请求
前端·javascript·taro