@chrissong/multi-part-upload

multi part upload

Usage no npm install needed!

<script type="module">
  import chrissongMultiPartUpload from 'https://cdn.skypack.dev/@chrissong/multi-part-upload';
</script>

README

multi-part-upload

基于 axios 的自定义的分片上传模块,支持切片大小设置和并行上传

使用   

安装

yarn add @chrissong/multi-part-upload
或者
npm install  @chrissong/multi-part-upload --save

基本用法

下面以在 React 项目中结合 antdUpload 组件实现分片上传,Upload 上的 action、data、headers、withCredentials、onError、onProgress、onSuccess 等属性将作为

import multiPartUpload from "@chrissong/multi-part-upload";

const ShareMultiPartUpload = () => {
  const [dataList, setDataList] = useState([]);

  // 检查文件
  const checkUpload = (file: any) => {
    // 插入文件
    setDataList([
      // @ts-ignore
      ...dataList,
      {
        id: file.uid,
        type: file.type.split('/')[0],
        url: null,
        progress: 0,
        selected: true,
        fileName: file.name,
      },
    ]);

    return true;
  };

  // 上传回调
  const uploadOnChangeParams = {
    // 上传完成
    onSuccess: (res: any, file: any) => {
      setDataList(
        // @ts-ignore
        dataList.map((item: any) => {
          if (file.uid === item.id) {
            return {
              ...item,
              progress: 100,
              url: _.get(res, 'data.objUrl', ''),
            };
          }
          return item;
        }),
      );
    },
    // 上传失败
    onError: (_err: any, file: any) => {
      const { type } = file;
      const mediaType =
        type === 'image' ? '图片' : type === 'video' ? '视频' : '文件';
      message.error(`${mediaType}上传失败!`);
    },
    // 上传进度
    onProgress: ({ percent }: any, file: any) => {
      setDataList(
        // @ts-ignore
        dataList.map((item: any) => {
          if (file.uid === item.id) {
            return {
              ...item,
              progress: Math.floor(percent),
            };
          }
          return item;
        }),
      );
    },
  };

  return (
    <section>
      <Upload
        action={action}
        accept="image/*,video/*"
        showUploadList={false}
        beforeUpload={checkUpload}
        {...uploadOnChangeParams}
        customRequest={(pramas) =>
          multiPartUpload({
            ...pramas,
            chunkSize: 10 * 1024 * 1024,
            parallel:false,
            data: (file: any, chunk: any, pre: any) => {
              const { size, name } = file;
              const { chunkCount, chunkIndex, chunkStart, chunkSize } = chunk;
              const formaData = {
                downloadFlag: 1,
                publicFlag: true, // 话题回答和评论的上传都是公开的
                appendFlag: chunkCount > 1,
                position: chunkStart,
                times: chunkCount >= chunkIndex + 1 ? chunkIndex + 1 : -1,
                totalSize: size,
                currentSize: chunkSize,
                fileName: name,
                uploadId: _.get(pre, 'data.data.uploadId') || null,
                objectKey: _.get(pre, 'data.data.objectKey') || null,
              };
              //  这里需要判断是否是第一次是否是第一次上传
              return pre
                ? formaData
                : _.omit(formaData, ['uploadId', 'objectKey']);
            },
          })
        }
      >
        <Button type="primary"> 共享平台项目分片上传</Button>
      </Upload>
  );
};

这里特别说明chunkSize 表示切片的大小,将在上传的时候自动分成每片 chunkSize 大小单位是 b。当parallel值为 false 的时候表示分片串行执行,data属性作为函数执行时第二个参数chunk表示当前分片信息,第三个参数pre表示上一次请求的返回值;该示例是multiPartUpload在移动共享项目大文件分片上传的应用,受制于后端接口逻辑,使用的较慢的串行分片上传;

multiPartUpload也支持并行分片上传,如下

<Upload
  action={action}
  accept="image/*,video/*"
  showUploadList={false}
  beforeUpload={checkUpload}
  {...uploadOnChangeParams}
  customRequest={(pramas) => {
    multiPartUpload({
      ...pramas,
      chunkSize: 5 * 1024 * 1024,
      parallel: 3,
      data: (file, chunk) => {
        const { size, name, uid } = file;
        const { chunkCount, chunkIndex, chunkStart, chunkSize } = chunk;
        return {
          name: name,
          hash: uid,
          total: chunkCount,
          index: chunkIndex,
        };
      },
    });
  }}
>
  <Button type="primary"> 并行分片上传</Button>
</Upload>

设置parallel值为一个数字类型将代表可一次并行发请求数(最大为 6),并行分片上传data作为函数执行的第三个参数将为 undefined;

API

参数 说明 类型 默认值
action 上传的地址 string
chunkSize 分片参数 number | boolean false
data 上传所需额外参数或返回上传额外参数的方法 object|(file,chunk?,pre?) => object
headers 设置上传的请求头部,IE10 以上有效 object
parallel 并行上传请求数 number | boolean false
withCredentials 上传请求时是否携带 cookie boolean false
onError 上传失败回调 (event: Error | ProgressEvent, file: FileType) => void undefine
onProgress 上传进度回调 (event: UploadProgressEvent, file: FileType) undefine
onSuccess 上传成功回调 (body: any, file: FileType) => void; undefine