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 🙏

© 2026 – Pkg Stats / Ryan Hefner

chunk-file-upload

v1.0.11

Published

文件分片上传

Readme

chunk-file-load

文件分片上传工具

测试

具体实例及测试请在github进行fork后运行以下命令

  1. cmd分别命令执行查看相关示例 npm run start npm run server
  • 这里默认认为本机安装了node和nodemon
  1. cmd执行下面命令进行测试 npm run test
  • 需要安装jest

简单介绍

  • 工具可以使上传文件变为可控,包括多任务同时上传、暂停任务、取消任务以及查看上传进度、断点续传,但是中间相关细节需要后端进行配合 new
  • 此次更新增加了更多的文件上传流程控制,以及更改了相关api的名称,配合worker进行文件解析。
  • 分离了兼容小程序的上传方法,小程序端import { WeUpload } from 'chunk-file-upload', 反之import { Upload } from 'chunk-file-upload'

简单使用

//in react
import { Upload } from 'chunk-file-upload'

function UploadFile() {

    const onChange = (e) => {
        const [ file ] = e.target.files
        const upload = new Upload({
            lifecycle: {
                
            },
            config: {},
            ignores: []
        })
        upload.upload({
            file: {
                file
            },
            request: {
                uploadFn: (data) => {
                    //request(data)
                }
            }
        })
    }

    return (
        <input type="file" onChange={onChange} />
    )

}

使用 upload.upload(...args) 上传文件

  • 传入相关参数
  • 支持传入多个任务参数
  • 文件会自动进行分片并上传
  • 返回自动生成的唯一文件名称集合
const upload = new Upload()
let config: {
    config?: {
        retry?: {
            times: number
        }
        chunkSize?: number
        parseIgnore?: boolean 
    }
    file: {
        mime?: string
        file: File | Blob | ArrayBuffer | string
        md5?: string
        chunks?: (File | Blob | ArrayBuffer | string)[]
    }
    lifecycle /*具体查看下面生命周期*/
    request: {
        exitDataFn?: (params: {
            filename: string
            md5: string
            suffix: string
            size: number
            chunkSize: number
            chunksLength: number
        }, name: Symbol) => Promise<{
            data: Array<number> | string | number
            [key: string]: any
        }>
        uploadFn: (data: FormData | { 
            file: Blob | string
            md5: string
            index: number 
        }, name: Symbol) => Promise<{
            data: Array<number> | string | number
            [key: string]: any
        }>
        completeFn?: (params : { name: Symbol, md5: string }) => any
        callback?: (err: any, data: any) => any
    }
} = {
    file: {
        file,   //文件 支持file blob arraybuffer 以及base64格式的文件, 并且尽量传递mime类型,否则后台对文件合并时无法获取文件mime类型
        md5, //加密后的名称,用于跳过加密过程,配合chunks使用,单独传递无效
        mime, //mime类型(/.+\/.+/)
        chunks //事先完成的分片,用于跳过分片过程,具体参照下面的 uploading 方法
    },
    request: {
        exitDataFn, //验证后端是否存在文件的方法(可选,不传则每一次上传都会全部重新上传)
        uploadFn,   //上传方法
        completeFn, //完成上传后通知后端的方法(可选,如果后端有自己的验证方式则无需传递)
        callback,    //回调函数(可选)
    },
    config: {   //相关配置(可选)
        retry: { //是否错误重试 默认不重试
            times
        },
        chunkSize //分片大小 默认5MB
        parseIgnore //跳过文件解析
    },
}
let names = upload.upload(config)
  • 相关回调参数
exitDatFn({
    filename: '文件名称',
    md5: '加密文件名称',
    suffix: '文件后缀名称',
    size: '文件大小',
    chunkSize: '文件单分片大小',
    chunksLength: '文件总分片数量'
}, name)
uploadFn(data/*
包含文件的formData
{
    file: '分片文件',
    md5: '加密文件名称',
    index: '当前文件分片索引'
}
*如果不支持formData则为普通对象/)
completeFn({
    name: '上传队列中的文件唯一索引',
    md5: '加密文件名称'
})
callback(err/*任务错误信息, 没有则为null*/, res/*不为null则表示任务成功*/)
  • about exitDataFn 因为无法得知服务端的数据返回格式, 可以进行相应的定义来适应数据格式
  • like this
exitDataFn: function(...someparams) {
    //得到相应的数据
    const data = {  }

    //返回格式(如果服务端指定为全部上传完成,格式为false)
    return {
        data: [/*数字或字符串数字索引*/] || false
    }
}

响应类型格式如下:

    type response = {
        //data索引必传
        data: Array<string> | number | string | false
        [key: string]: any
    }
  • about callback 第一参数为error, 第二参数为completeFn或是在秒传时exitDataFndata外的其余数据 like this callback(err: null | any, data: null | any) => any
  • 使用不同类型的文件
    const upload = new Upload()
    upload.upload({
        file: {
            file: new File([new ArrayBuffer(1024)], 'filename'), 
        },
        request: {
            uploadFn
        },
    })
  • 预先解析完成(可跳过解析流程)
    const upload = new Upload()
    upload.upload({
        file: {
            file: new File([new ArrayBuffer(1024)], 'filename'), 
            md5: 'xxxxxxxxxxxx'
        },
        request: {
            uploadFn
        },
    })
  • 预先完成分片
    const upload = new Upload()
    upload.upload({
        file: {
            md5: 'xxxxxxxxxxxx',
            mime: 'image/png',
            chunks: [ new ArrayBuffer(1024), new Blob([new ArrayBuffer(1024)]) ]
        },
        request: {
            uploadFn
        },
    })

调用 upload.add(...tasks) 加入上传文件队列

  • 传入相关参数(参数类型与上面的upload方法相同)
  • 支持传入多个任务参数
  • 不会自动触发上传,需要调用upload.deal
  • 返回自动生成的唯一文件名称集合
//支持任意格式的对象参数,但是需要保证对象内的必要参数都正确
let names = upload.add({
    file: {
        file: new File([new ArrayBuffer(1024)], 'filename')
    },   
    request: {
        exitDataFn, 
        uploadFn,  
        completeFn,
        callback   
    } 
})

调用 upload.deal(...names) 执行指定的队列任务

  • 参数为绑定上传任务时返回的给定任务文件名称
  • 支持传入多个参数
  • 返回所有状态的任务名称
const [ name ] = upload.add(/*params...*/)
upload.deal(name)

upload.uploading(...tasks)

  • 效果类似于上面的upload
  • 但是此方法适用于在外部事先完成了分片工作,并配置chunks 或者是恢复之前上传失败的任务
  • 如果不是恢复上传的任务
  1. 分片的大小不能超过指定的单个分片大小,否则会失败
  2. md5chunks都有配置,则可以跳过加密的过程
  3. 只有chunks则需要经过加密
  4. 分片同上类型所示,且不限制需要相同类型
  5. 如果没有配置传递原始文件,则需要传递mime属性

保证分片列表的顺序正确
分片会被统一转换成一种格式,按照api的支持程度顺序为Blob -> File -> base64

搭配生命周期更细粒度的控制上传过程

    type responseType = boolean | Promise<boolean>
    type TLifeCycleParams = {
        name: Symbol
        task: TWrapperTask //参照api
    }
    //序列化前
    beforeRead?: (params: TLifeCycleParams, response?: any) => responseType
    //序列化中
    reading?: (params: TLifeCycleParams & { current: number, total: number }, response?: any) => responseType
    //MD5序列化后,检查请求前
    beforeCheck?: (params: TLifeCycleParams, response?: any) => responseType
    //检查请求响应后
    afterCheck?: (params: TLifeCycleParams & { isExists: boolean }, response?: any) => responseType
    //分片上传后(多次执行)
    uploading?: (params: TLifeCycleParams & { current: number, total: number, complete: number }, response?: any) => responseType
    //触发暂停响应后
    afterStop?: (params: TLifeCycleParams & { current: number }, response?: any) => responseType
    //触发取消响应后
    afterCancel?: (params: TLifeCycleParams & { current: number }, response?: any) => responseType
    //完成请求前
    beforeComplete?: (params: TLifeCycleParams & { isExists: boolean }, response?: any) => responseType
    //完成请求后
    afterComplete?: (params: TLifeCycleParams & { success: boolean }, response?: any) => responseType
    //触发重试任务执行
    retry?: (params: TLifeCycleParams & { rest: number }, response?: any) => responseType

生命周期包括全局和单一任务生命周期

  • 全局
const upload = new Upload({
    lifecycle: {
        beforeCheck() {
            //在文件检查前停止上传(相当于stop)
            return false
        }
    }
})
  • 局部
    const upload = new Upload()
    upload.add({
        /*其他配置*/
        lifecycle: {
            beforeUpload({ name, task }) {
                //暂停
                this.stop(name)
                //查看进度
                console.log(task.watch(), this.watch(name))
                //取消
                this.cancel(name)
            }
        }
    })
  • 全局的生命周期执行在局部之前
  • 如果希望能使用this来获取实例属性方法等,请不要使用箭头函数
  • 返回false或reject则停止后续生命周期执行

API

dispose

  • 销毁实例 upload.dispose()

start

  • 执行指定队列任务,与deal功能类似
  • 对于处于上传中的任务无效 upload.start(...names)

stop

  • 暂停上传中的任务
  • 返回执行暂停操作的任务文件名称集合
  • 只对上传中的任务有效
  • 对于暂停的任务可以通过start继续上传
upload.stop(...names) //不传参数则暂停所有任务

cancel

  • 取消上传中的任务
  • 返回执行取消操作的任务文件名称集合
  • 只对上传中的任务有效
  • 一旦取消了上传任务则需要重新通过uploadadd等方法进行添加才能上传
upload.cancel(...names)

cancelAdd

  • 取消队列中的任务
  • 返回被取消绑定的任务文件名称集合
  • 只对加入队列但还处于等待状态的任务有效
upload.cancelAdd(...names)    //不传则取消所有任务

resumeTask

  • 恢复之前失败或取消的任务
  • 需要传递完整的任务格式
upload.resumeTask(...tasks) 

watch

  • 查看上传进度
  • 返回指定任务的上传进度集合
  • 你也可以在任务中的watch属性方法来获取对应的任务进度。
//return [{ error, name, progress, status, total, current, complete } || null]
upload.watch(...names) //不传则返回所有进度

getTask

  • 获取指定的任务信息

getOriginFile

  • 获取源文件

getStatus

  • 获取任务当前状态

static API

install

  • 插件注册(具体查看下方Changelog 1.0.7)

isSupport

  • 当前环境是否支持

Changelog

1.0.10
1.0.9
1.0.7
1.0.6
1.0.5

总结

文件分片上传是为了能在后端限制上传文件大小的情况下,也为了能有更好的用户体验,将体积大的文件分成等体积的小文件进行分别上传,也保证了当用户在不明情况下中断上传可以继续上传。