16

在我的网页中,用户应该上传一个压缩文件。压缩文件中有 2 个文件:另一个 zip 文件和一个 txt 文件。在我的服务器上,收到 zip 后,我想解压缩 zip 文件以提取 zip 和 txt 文件,然后将这 2 个文件移动到预定义的文件夹中。我有一段代码可以提取 zip 文件,但数据似乎不正确。首先,当应该只有 1 个 txt 文件时,它解压缩了一个 zip 和 2 个 txt 文件。它创建了一个额外的“未定义”txt 文件。此外,在我的 txt 文件中,它被替换为以下文本,而不是原始数据:'[undefined] [undefined]'。
谁可以帮我这个事?以下是我的代码:

var JSZip = require('JSZip');

fs.readFile( filePath, function(err, data){
  if (!err){
    var zip = new JSZip();
    JSZip.loadAsync(data).then(function(zip){
      object.keys(zip.files).forEach(function(filename){
        var content = zip.files[filename];
        var dest = path + filename;
        fs.writeFileSync(dest, content);
      });
    });
  }
});
4

4 回答 4

26

这是我正在使用的工作版本:

var jsZip = require('jszip')
jsZip.loadAsync(file).then(function (zip) {
  Object.keys(zip.files).forEach(function (filename) {
    zip.files[filename].async('string').then(function (fileData) {
      console.log(fileData) // These are your file contents      
    })
  })
})

您可以从http://stuk.github.io/jszip/documentation/examples.html获得所需的大部分信息,但要在一个地方获得有点困难,您必须四处看看。

于 2016-10-10T18:55:24.077 回答
15

在他们的文档中进行了一些挖掘,但他们有一个示例展示了如何从 ZIP 中读取文件内容。

您将获得描述ZIP 内容但不是实际内容的对象。这是一个调整后的版本:

var JSZip = require('JSZip');

fs.readFile(filePath, function(err, data) {
    if (!err) {
        var zip = new JSZip();
        zip.loadAsync(data).then(function(contents) {
            Object.keys(contents.files).forEach(function(filename) {
                zip.file(filename).async('nodebuffer').then(function(content) {
                    var dest = path + filename;
                    fs.writeFileSync(dest, content);
                });
            });
        });
    }
});
于 2016-09-05T05:38:03.360 回答
0

这个答案很cordova-plugin-file具体。

文档中所述:

必须连续创建目录条目。例如,如果 dir1 不存在,调用 fs.root.getDirectory('dir1/dir2', {create:true}, successCallback, errorCallback) 将失败。

我几乎可以肯定,当前接受的答案不能保证文件内容/文件夹总是以相同的顺序检索。这可能会导致 API 出现问题,例如cordova-plugin-file. 尤其是当您调用另一个异步函数以在文件系统上异步创建目录时。

您可能希望先过滤 zip 存档的目录并以同步方式创建它们,然后再继续提取已回答的其他文件:

const directoryNames = Object.keys(zip.files).filter(name => zip.files[name].dir);
for (const directoryName of directoryNames) {
    await this.createDirectory(directoryName, dirEntry);
}
// ...

private createDirectory = (dirName: string, dirEntry: DirectoryEntry) => {
    const promise = new Promise<DirectoryEntry>(resolve, reject) => {
        dirEntry.getDirectory(dirName, { create: true }, dirEntry => {
            resolve(dirEntry);
        }, fileError => reject(fileError));
    });
    return promise;
}
于 2019-07-23T09:57:44.673 回答
0

这是我在 Angular 10 中将单个文件写入具有自定义扩展名的 zip 的策略,然后读取相同的 zip 以检索 json。

将文件打包成 zip(支持自定义文件结尾)

import { saveAs } from 'file-saver';
import * as JSZip from 'jszip';

export async function exportJson(
  filename: string,
  jsonToExport: string,
  fileNameEnding = '.zip'
): Promise<string> {
  const jsonFile = new Blob([jsonToExport], {
    type: 'application/json',
  });

  if (!jsonFile) return Promise.reject('Error converting file to JSON');

  const zipper = new JSZip();
  zipper.file(`${filename}.json`, jsonFile);
  const zippedFile = await zipper.generateAsync({ type: 'blob' });

  const exportFilename = `${filename}${fileNameEnding}`;
  saveAs(zippedFile, exportFilename);
  return Promise.resolve(exportFilename);
}

从 zip 中读取文件内容

// file parameter retrieved from an input type=file
export async function readExportedJson(file: File): Promise<Blob> {
  const zipper = new JSZip();
  const unzippedFiles = await zipper.loadAsync(file);
  return Promise.resolve(unzippedFiles).then(unzipped => {
    if (!Object.keys(unzipped.files).length) {
      return Promise.reject('No file was found');
    }
    return unzipped.files[Object.keys(unzipped.files)[0]];
  }).then(unzippedFile => zipper.file(unzippedFile.name).async('string'));
}
于 2021-11-11T21:00:09.330 回答