npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

yuuki-uploader-vue

v1.0.3

Published

vue3实现的大文件分片上传器

Downloads

5

Readme

Yuuki-Uploader

文件上传器,实现了文件分片上传、分片检测、断点续传等功能。

采用 hooks 设计方式,分别使用 React 和 Vue3 实现。

安装

使用 vue 版本运行

npm install yuuki-uploader-vue

使用 react 版本运行

npm install yuuki-uploader-react

基本用法

上传流程简述

在文件添加时,会先计算文件的 MD5 值(Spark-MD5实现),此时文件状态为calculating,在 MD5 值计算完成后,文件进入waiting状态

使用 upload 方法即可使waiting状态的文件其进入uploading状态,upload 方法调用时,首先会发送预检请求(POST 请求),根据 http 状态码决定后续是否上传。在实际文件块上传之前,会先发送不带有文件块的测试请求(GET 请求),同样根据 http 状态码决定是否实际上传请求(POST 请求)

所有分块上传完毕后,文件进入complete状态,此时发送合并请求(POST 请求),根据 http 状态码决定上传是否成功,上传成功则进入success状态

文件暂停时会进入pause状态,使用 resume 方法恢复时,会重新发送所有的测试请求(GET 请求),确定还未发送的文件块

上述任何一个环节出现问题,文件都会进入fail状态

  • 默认请求成功的状态码(预检和测试请求后会实际上传): 200, 201, 202

  • 默认跳过上传的状态码(预检和测试请求后不会实际上传): 204, 205, 206

  • 默认上传失败的状态码(上传器终止所有与失败文件相关的请求): 400, 404, 415, 500, 501

  • 其它状态码和网络错误等: 上传器会尝试重传直到达到重传次数上限

请求中的基本数据

所有请求都会包含文件的基本信息,如下图 FileInformation 所示

interface FileInformation {
  totalChunks: number //总块数
  chunkSize: number //预设分块标准大小
  filename: string //文件名
  totalSize: number //总文件大小
  hash: string //文件md5
  webkitRelativePath: string //上传文件夹时文件路径
}

分块相关的请求会携带分块相关的一些数据,如下图所示

interface TestChunk extends FileInformation {
  chunkIndex: number //当前块号
  currentSize: number //当前块大小
}

interface Chunk extends TestChunk {
  file: Blob //文件流
}

Uploader 构造函数

两个版本的都通过 useUploader 函数返回一个 Uploader 对象

const useUploader = (uploaderOption?: Partial<UploaderOption>): Uploader

其中,Vue 版本和 React 版本在数据响应式和注册上传器方面存在一定差异,其余部分一致

Vue 版本 Uploader

export interface Uploader {
  uploadList: ComputedRef<UploadFile[]> //响应式文件列表
  register: (element: Ref<HTMLElement | undefined>) => void //将元素注册为可点击上传文件
  registerDrop: (element: Ref<HTMLElement | undefined>) => void //将元素注册为拖拽上传区域
  addFile: (rawFile: File) => Promise<void> //添加单个文件
  addFileList: (fileList: File[]) => Promise<void> //添加多个文件
  removeFile: (uploadFile: UploadFile) => void //移除单个文件
  unRegister: () => void //解除注册元素的点击上传功能
  unRegisterDrop: () => void //解除注册元素的拖拽上传功能
  upload: (uploadFile: UploadFile) => void //上传指定的文件
  pause: (uploadFile: UploadFile) => void //暂停指定的文件
  cancel: (uploadFile: UploadFile) => void //取消指定文件的上传
  resume: (uploadFile: UploadFile) => void //恢复指定文件的上传
  uploadAll: () => void //上传文件列表中所有waiting状态的文件
  pauseAll: () => void //暂停文件列表中所有uploading状态的文件
  cancelAll: () => void //取消上传所有uploading和pause状态的文件
}

React 版本的 Uploader

export interface Uploader {
  uploadList: UploadFile[] //响应式文件列表
  register: (element: RefObject<HTMLElement>) => void //将元素注册为可点击上传文件
  registerDrop: (element: RefObject<HTMLElement>) => void //将元素注册为拖拽上传区域
  addFile: (rawFile: File) => Promise<void> //添加单个文件
  addFileList: (fileList: File[]) => Promise<void> //添加多个文件
  removeFile: (uploadFile: UploadFile) => void //移除单个文件
  unRegister: () => void //解除注册元素的点击上传功能
  unRegisterDrop: () => void //解除注册元素的拖拽上传功能
  upload: (uploadFile: UploadFile) => void //上传指定的文件
  pause: (uploadFile: UploadFile) => void //暂停指定的文件
  cancel: (uploadFile: UploadFile) => void //取消指定文件的上传
  resume: (uploadFile: UploadFile) => void //恢复指定文件的上传
  uploadAll: () => void //上传文件列表中所有waiting状态的文件
  pauseAll: () => void //暂停文件列表中所有uploading状态的文件
  cancelAll: () => void //取消上传所有uploading和pause状态的文件
}

Tips: React 版本返回的 uploadList 使用 useState 实现的状态变量,你无需维护该属性,它会自动实现响应式更新

UploaderOption 配置项

在初始化时,你可以通过填入不同的配置项自定义 Uploader

export interface UploaderOption {
  accept: string //接受的文件类型,与input标签的accept功能相同,默认为''
  multiple: boolean //文件多选(multiple实现),默认为true
  directoryMode: boolean //选择文件夹上传(multiple失效),默认为false
  chunkSize: number //分块大小(byte),默认为2*1024*1024
  target: string //分块上传目标url,默认为'/'
  mergeTarget: string //合并请求目标url,默认为'/'
  precheckTarget: string //预检请求目标url,默认为'/'
  concurrency: number //请求最大并发数量,默认为3
  headers: Record<string, string> //自定义请求头,默认为{}
  withCredentials: boolean //是否携带凭证,默认为false
  retryCount: number //失败重试次数,默认为3
  progressCallbacksInterval: number //progress回调函数最小间隔(ms),默认200
  successCodes: number[] //认为是上传成功的状态码(测试和预检请求后会发送实际上传请求),默认为[200,201,202]
  skipCodes: number[] //认为是文件或分块已存在的状态码(测试和预检请求后不再发送实际上传请求),默认为[204,205,206]
  failCodes: number[] //认为是上传失败的状态码(不会再重新发送和失败文件相关的任何请求),默认为[400, 404, 415, 500, 501]
  data?: (uploadFile: Readonly<UploadRawFile>) => Record<string, string | number> //测试分块和上传分块请求中发送的自定义数据
  mergeData?: (uploadFile: Readonly<UploadRawFile>) => Record<string, any> //合并请求中发送的自定义数据
  precheckData?: (uploadFile: Readonly<UploadRawFile>) => Record<string, any> //预检请求中发送的自定义数据
}

Uploader 监听事件

导出了 EventHandler 类型提供监听事件的定义,但使用时仍然定义在 UploaderOption 中(UploaderOption 类型包含了 EventHandler 类型)

export interface EventHandler {
  // 拖拽相关事件
  onDragEnter?: (event: DragEvent) => void //文件进入拖拽区域调用
  onDragOver?: (event: DragEvent) => void //文件在拖拽区域中反复调用
  onDragLeave?: (event: DragEvent) => void //文件离开拖拽区域中调用

  //文件相关事件
  onFileAdded?: (file: File) => Awaitble<boolean | void> //文件添加前调用(支持返回Promise)
  onFileReady?: (file: UploadFile) => Awaitble<void> //文件计算完成准备就绪后调用
  onFileRemoved?: (file: UploadFile) => void //文件被移除后调用
  onFileStart?: (file: UploadFile) => void //文件开始上传时调用
  onFileProgress?: (file: UploadFile) => void //文件上传中调用
  onFilePause?: (file: UploadFile) => void //文件暂停时调用
  onFileCancel?: (file: UploadFile) => void //文件被取消后调用
  onFileComplete?: (file: UploadFile) => void //文件所有分块上传成功后调用
  onFileSuccess?: (file: UploadFile) => void //文件上传成功后调用
  onFileFail?: (file: UploadFile, error: Error) => void //文件上传失败后调用
}

type Awaitble<T> = T | Promise<T>

UploadFile

响应式文件列表中维护的文件的类型

export interface UploadFile {
  uid: number //文件uid
  name: string //文件名,同原生文件名
  size: number //文件大小,同原生文件大小
  type: string //文件类型,同原生文件类型
  progress: number //文件进度,0~100保留一位小数
  currentSpeed: number //文件瞬时速度(单位bytpe/s)
  averageSpeed: number //文件平均速度(单位bytpe/s)
  status: UploadStatus //文件状态
  raw: UploadRawFile //内部API使用的文件对象
}

export type UploadStatus =
  | 'calculating'
  | 'waiting'
  | 'uploading'
  | 'compelete'
  | 'pause'
  | 'success'
  | 'fail'

简单示例

源代码中提供了简单的上传示例,clone 代码并运行pnpm install后,可以运行pnpm dev:vuepnpm dev:react启动 vue 示例或 react 示例,同时需要运行pnpm dev:server启动 node.js 示例服务。

作者附

写了好几个版本的,还是垃圾的没法看,路还是很漫长啊!