web-dev-qa-db-ja.com

JavaScriptでJSZIPを使用して圧縮ファイルを抽出する

私のWebページでは、ユーザーは圧縮ファイルをアップロードすることになっています。 zipファイル内には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);
      });
    });
  }
});
8
Cherple

ドキュメントを少し掘り下げましたが、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);
                });
            });
        });
    }
});
8
geekonaut

これは私が使用している作業バージョンです:

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 から取得できますが、1か所で取得するのは少し難しいので、見回す必要があります少し。

16
webnoob

この回答はcordova-plugin-file固有です。

docs で述べたように:

ディレクトリエントリは連続して作成する必要があります。たとえば、dir1が存在しない場合、fs.root.getDirectory( 'dir1/dir2'、{create:true}、successCallback、errorCallback)の呼び出しは失敗します。

現在受け入れられている回答では、ファイルコンテンツ/フォルダーが常に同じ順序で取得されることを保証できないことはほぼ間違いありません。これにより、cordova-plugin-fileなどのAPIで問題が発生する可能性があります。特に、別の非同期関数を呼び出して、非同期でファイルシステムにディレクトリを作成する場合。

すでに回答されているように他のファイルの抽出を続ける前に、まず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;
}
0
Yannic Hamann