我正在尝试分部分(.zip、.z01、.z02)等下载来自 api 调用的拆分 zip 文件。
在 Javascript 中,我想即时下载这些文件并创建一个组合的 .zip 文件,然后保存解压缩的文件。 (我不需要创建组合 zip)我只需要 test.pdf 文件,该文件已被拆分为多个 zip。我想下载那个pdf文件。
例如
test.pdf (18 mb) 分为 (.zip 10mb) 和 (.z01 8mb) 两个 zip 文件。目前我正在将它们下载为 blob,然后将它们合并。生成的 zip 已损坏。下面是我试过的代码。
Promise.all([
axios.get(`https://testapi.com/folder/file.zip`, {
responseType: "blob",
headers: {
Accept: "application/json",
},
}),
axios.get(`https://testapi.com/folder/file.z01`, {
responseType: "blob",
headers: {
Accept: "application/json",
},
}),
]).then((obj) => {
let blob: any = [];
obj.forEach((e: any) => {
blob.push(e.data);
});
const newBlob = new Blob(blob, { type: "octet/stream" });
saveAs(newBlob, "zip.zip"); // but it's currupted
});
最佳答案
您可以使用 JSZip和 FileSaver为了实现这一点。请注意,input
中的文件按字母顺序排列。所以这个片段需要你的文件相应地命名。我使用了 input
为了使测试更容易,您可以轻松地将其调整为每个文件的 axios 请求。
该代码段实际上在此网页上不起作用,因为代码段 iframe 的政策不允许下载,因此您必须通过其他方式尝试。
const objectWithoutProperties = (obj, keys) => {
const target = {};
for (let i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
}
const mergeFiles = (a, b) => {
if (!a) return b;
const intersect = Object.keys(a.files).filter((x) =>
Object.keys(b.files).includes(x)
);
a.files = { ...a.files, ...objectWithoutProperties(b.files, intersect) };
return Promise.all(
intersect.map((file) =>
Promise.all([
a.file(file).async("arraybuffer"),
b.file(file).async("arraybuffer"),
])
.then((x) => new Blob(x))
.then((x) => a.file(file, x))
)
).then(() => a);
};
const MultipleZipMerger = () => {
function change(e) {
Promise.all([...e.target.files].map(JSZip.loadAsync))
.then((x) =>
x.reduce(
(acc, cur) => acc.then((x) => mergeFiles(x, cur)),
Promise.resolve()
)
)
.then((x) => x.generateAsync({ type: "blob" }))
.then((x) => saveAs(x, "hello.zip"));
}
return <input onChange={change} type="file" multiple />;
};
ReactDOM.render(<MultipleZipMerger />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.6.0/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.1.0/jszip-utils.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.0/FileSaver.min.js"></script>
<div id="root"></div>
这是此代码的独立版本,您可以将其作为本地文件进行测试:
<!doctype html>
<html>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.6.0/jszip.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.1.0/jszip-utils.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.0/FileSaver.min.js"></script>
<div id="root"></div>
<script>
const objectWithoutProperties = (obj, keys) => {
const target = {};
for (let i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
}
const mergeFiles = (a, b) => {
if (!a) return b;
const intersect = Object.keys(a.files).filter((x) =>
Object.keys(b.files).includes(x)
);
a.files = { ...a.files, ...objectWithoutProperties(b.files, intersect) };
return Promise.all(
intersect.map((file) =>
Promise.all([
a.file(file).async("arraybuffer"),
b.file(file).async("arraybuffer"),
])
.then((x) => new Blob(x))
.then((x) => a.file(file, x))
)
).then(() => a);
};
const MultipleZipMerger = () => {
function change(e) {
Promise.all([...e.target.files].map(JSZip.loadAsync))
.then((x) =>
x.reduce(
(acc, cur) => acc.then((x) => mergeFiles(x, cur)),
Promise.resolve()
)
)
.then((x) => x.generateAsync({ type: "blob" }))
.then((x) => saveAs(x, "hello.zip"));
}
return React.createElement("input", {
onChange: change,
type: "file",
multiple: true,
});
};
ReactDOM.render(
React.createElement(MultipleZipMerger, null),
document.getElementById("root")
);
</script>
</body>
</html>
关于javascript - 如何在 javascript 中合并和解压缩(.zip、.z01、.z02)(仅限客户端)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67846534/