【问题标题】:Split array of files in N chunks将文件数组拆分为 N 个块
【发布时间】:2021-09-19 14:23:37
【问题描述】:

我有一个文件数组,我必须根据文件大小将其拆分成块,这样:

[10MB 图像、5MB 图像、5MB 图像] 最大大小为 20MB 并不需要拆分,但 [10MB、10MB、15MB] 将拆分为 [10MB、10MB] 和 [15MB]强>

然后我必须执行获取文件并将它们放入表单数据以将其发送到端点的功能。

我想要做的是返回一个包含所需块的FormData 数组。

我怎样才能做到这一点?

这是当前函数:

const newImagesToEndpoint = (newFiles: NewImagesInterface[]) => {
    const newImages = new FormData();
    newFiles.forEach(img => {
      newImages.append('images[]', (img.file as unknown) as File);
    });
    return newImages;
  };

【问题讨论】:

  • 你能解释一下“return n FormData”是什么意思吗?我已经阅读并重读了倒数第二行几次,这有点令人困惑。你还没有计算出块吗?
  • 一个 FormData 数组,所以如果初始数组将被分成 3 个块,我将拥有一个由 3 个 FormData 对象组成的数组
  • 哦,我明白了,你仍然需要实现分块。您自己已经尝试过什么?
  • 我创建了一个 const "maxSize" 来检查它何时大于 limitFileSize 并将文件放入 formData,但我不知道如何获取其余文件并将其放入另一个一。我想这不是实现它的正确方法

标签: javascript arrays reactjs typescript chunks


【解决方案1】:

你的问题不是很清楚。我理解您所说的拆分是指通过多个 http 调用从客户端发送到服务器,而不是拆分单个文件?

假设NewImagesInterface 有一个size: number 字段,那么是这样的吗?

function sendChunks(images: NewImagesInterface[], limit = 20e6): FormData[] {
  const out: FormData[] = [], chunkSize = 0;
  for(const img of images) {
    if(img.size > limit)
      throw new Error('each individual image must be < ' + limit);
    if(!out.length || chunkSize + img.size > limit) {
      chunkSize = 0;
      out.push(new FormData[]);
    }
    out[out.length-1].append('images[]', (img.file as unknown) as File);
    chunkSize += img.size;
    return out;
};

还要注意类型,毕竟这是打字稿的重点。如果要输出FormData 的数组,则函数的返回类型必须为FormData[]。这意味着您的函数将在某些时候构建并返回一个数组。如果你是这样想的,从类型要求开始,并将它们应用到你如何构建你的代码,它将帮助你想出一个解决方案。

【讨论】:

  • 对不起,如果我不能说得很清楚,但你明白了,我正在尝试你的解决方案,谢谢!
【解决方案2】:

这是我快速想出的算法。这是一个有点贪心的算法,按大小 DESC 排序,然后迭代排序后的数组并将文件“打包”到具有剩余可用性的数组中。它最终将中间结果映射到仅由块组成的数组。

注意:显然您需要对此进行调整以实际使用您的文件数组并正确计算和比较文件大小。

const MAX_CHUNK_SIZE = 20;

const chunkFiles = (filesArray) =>
  filesArray
    .slice()
    .sort((a, b) => b.size - a.size)
    .reduce((chunks, file) => {
      const chunk = chunks.find((chunk) => chunk.available >= file.size);

      if (chunk) {
        chunk.array.push(file);
        chunk.available -= file.size;
      } else {
        chunks.push({
          array: [file],
          available: MAX_CHUNK_SIZE - file.size
        });
      }
      return chunks;
    }, [])
    .map(({ array }) => array);

const filesToProcess = [
  [{ size: 10 }, { size: 5 }, { size: 5 }],
  [{ size: 10 }, { size: 10 }, { size: 15 }],
  [{ size: 10 }, { size: 3 }, { size: 7 }, { size: 10 }, { size: 15 }]
];

filesToProcess.forEach((files, i) => {
  const chunks = chunkFiles(files);
  console.log(JSON.stringify(chunks));
});

这些文件块数组可以传递给您的newImagesToEndpoint 实用程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 2013-03-12
    • 2017-03-03
    • 1970-01-01
    • 2012-07-04
    • 2020-09-16
    相关资源
    最近更新 更多