如何使用客户端 JS 压缩用户上传的用户上传文件夹?

How do you compress a user-uploaded a user-uploaded folder with client-side JS?

提问人:Liam Swayne 提问时间:11/17/2023 更新时间:11/17/2023 访问量:19

问:

我正在创建一个基本页面,该页面使用新的 CompressionStream API gzip 压缩功能来获取用户的文件夹并使用客户端 JS 将其压缩为 .gz。

下面是使用 gzip 进行压缩的示例:

const compressedReadableStream = inputReadableStream.pipeThrough(
  new CompressionStream("gzip"),
);

在此示例中,函数使用 gzip 解压缩 blob:

async function DecompressBlob(blob) {
  const ds = new DecompressionStream("gzip");
  const decompressedStream = blob.stream().pipeThrough(ds);
  return await new Response(decompressedStream).blob();
}

我已经让压缩和解压缩适用于文件上传,甚至让它适用于一次上传多个文件,但无法让它适用于目录,这使得它几乎毫无用处。

我尝试创建最基本的设置,但发现将目录压缩为文件只会使其成为文件,而不再是文件文件夹。这是我目前的设置:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>File Upload and Compression</title>
</head>
<body>

<input type="file" id="fileInput" multiple webkitdirectory>

<button onclick="groupAndCompress()">Group and Compress</button>

<script>
async function groupAndCompress() {
  const fileInput = document.getElementById('fileInput');
  const files = fileInput.files;

  if (files.length === 0) {
    alert('Please select at least one file or folder.');
    return;
  }

  const groupedFiles = groupFiles(files);
  const compressedBlob = await compressFiles(groupedFiles);

  // You can use the compressedBlob as needed (e.g., download or display)
  console.log('Compressed Blob:', compressedBlob);
}

function groupFiles(files) {
  const groupedFiles = {};

  for (const file of files) {
    const path = file.webkitRelativePath || file.name;

    if (!(path in groupedFiles)) {
      groupedFiles[path] = [];
    }

    groupedFiles[path].push(file);
  }

  return groupedFiles;
}

async function compressFiles(groupedFiles) {
  const compressedParts = [];

  for (const path in groupedFiles) {
    const files = groupedFiles[path];
    const blobs = await Promise.all(files.map(fileToBlob));
    const concatenatedBlob = new Blob(blobs, { type: 'application/zip' });

    const compressedStream = concatenatedBlob.stream().pipeThrough(new CompressionStream('gzip'));
    const compressedBlob = await new Response(compressedStream).blob();

    compressedParts.push(compressedBlob);
  }

  const finalBlob = new Blob(compressedParts, { type: 'application/zip' });
  return finalBlob;
}

function fileToBlob(file) {
  return new Promise((resolve) => {
    const reader = new FileReader();

    reader.onload = function () {
      resolve(new Blob([reader.result], { type: file.type }));
    };

    reader.readAsArrayBuffer(file);
  });
}
</script>

</body>
</html>

我知道 JSzip,但内置的 Web 功能可以更快地执行此操作,并且不需要获取脚本。

JavaScript HTML 压缩

评论

0赞 jabaa 11/17/2023
您将如何上传文件夹?我什至不知道这是可能的。
1赞 Liam Swayne 11/17/2023
@jabaa <input type=“file” 多个 webkit目录>可用于上传目录

答: 暂无答案