1.0.11 • Published 3 years ago

chunk-file-upload v1.0.11

Weekly downloads
3
License
ISC
Repository
github
Last release
3 years ago

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

总结

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

1.0.11

3 years ago

1.0.10

3 years ago

1.0.9

4 years ago

1.0.8

4 years ago

1.0.7

4 years ago

1.0.6

4 years ago

1.0.5

5 years ago

1.0.4

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago