unzip.Parse()した後にmaximum call stack size exceeded エラーが出てしまうので回避したい。

714 views
Skip to first unread message

meganetops

unread,
Feb 20, 2014, 8:50:06 PM2/20/14
to node...@googlegroups.com
はじめまして。

私はNodeを少し触って遊んでみているWebデザイナーです。
WordPressをダウンロードしてzipを解凍するコードを書いて動かしてみたところ、
maximum call stack size exceeded エラーが出てしまいいきずまってしまいました。

環境は、
OS:Window7
Node: v.0.10.24
です。
あと、zipの展開には「node-unzip」というものを使用させていただいております。

下記のコードで動かしてみているのですが何が原因となっていますでしょうか?

var http = require("http");
var fs = require("fs");
var unzip = require("unzip");

var savedir = "./tmp"
var output = fs.createWriteStream(savedir+"/wordpres-latest.zip");


var req = http.get(url,function(res){
res.pipe(output);

res.on("data",function(){
console.log("on-data・・・");
});
res.on("end",function(){
console.log("finish!!!!!!!!");
output.close();
fs.createReadStream(savedir+"/wordpres-latest.zip")
.pipe(unzip.Extract({ path: savedir }))
.on('error', function (err) { console.log('error', err); })
.on('close', function () { console.log('closed'); });
});
});

zipの解凍はできているようで、
展開されたファイルは出てきています。

よろしくお願いいたします。


Hiroshi Kuwabara

unread,
Feb 20, 2014, 11:17:07 PM2/20/14
to node...@googlegroups.com

node-unzipモジュールの中でpullstreamというモジュールが使われており、
そのモジュールがprocess.nextTickを再帰的に呼び出しているようです。

Error: (node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
    at maxTickWarn (node.js:375:15)
    at process.nextTick (node.js:480:9)
    at pullServiceRequest (/Users/.../node_modules/unzip/node_modules/pullstream/pullstream.js:48:17)
    at PullStream.<anonymous> (/Users/.../node_modules/unzip/node_modules/pullstream/pullstream.js:38:5)
    at PullStream.pull (/Users/.../node_modules/unzip/node_modules/pullstream/node_modules/over/overload.js:24:23)
    at /Users/.../node_modules/unzip/lib/parse.js:235:24
    at process._tickCallback (node.js:415:13)

--throw-deprecation もしくは --trace-deprecationオプションをつけて実行すると、
スタックトレースが吐出されるようになります。

node --throw-deprecation app.js


unzipする目的であれば、node組込みのzlibモジュールで代替できるかと思います。

meganetops

unread,
Feb 21, 2014, 12:36:38 AM2/21/14
to node...@googlegroups.com
Hiroshi Kuwabara 様

ありがとうございます。
--throw-deprecation もしくは --trace-deprecationオプションで
色々情報が得られるんですね!
検証が捗りそうです。ありがとうございます。

他力本願でnode-unzipモジュールを入れれば簡単かなと思ったのですが、
余計に遠回りになってしまっていたんですね・・・。
教えていただいたzlibモジュールで頑張ってみます。



2014年2月21日金曜日 13時17分07秒 UTC+9 Hiroshi Kuwabara:

meganetops

unread,
Feb 22, 2014, 4:09:45 AM2/22/14
to node...@googlegroups.com
node組込みのzlibモジュールにチャンレンジしてみました。

サンプルにあったような1ファイルだけを圧縮、解凍は動かせる事はできましたが、
ディレクトリを圧縮したzipを解凍ができませんでした・・・。
下記のようなコードでためしてみています。


var fs = require('fs');
var zlib = require("zlib");
var un_zip = zlib.createUnzip();

var inp = fs.createReadStream("wordpress-3.8.1-ja.zip");
var out = fs.createWriteStream("tmp/wp");

inp.pipe(un_zip).pipe(out);


下記のエラーが出てうまくいきませんでした。

events.js:72

        throw er; // Unhandled 'error' event

              ^

Error: incorrect header check

    at Zlib._binding.onerror (zlib.js:295:17)


エラーをもとに昨日からググってみましたが、
クライアントサイドのJSとWordpressを触るのにPHPを少しやっている私レベルでは
ちょっと歯がたちません(汗

何かヒントをいただけませんでしょうか。

よろしくお願いいたします。



2014年2月21日金曜日 10時50分06秒 UTC+9 meganetops:

Hiroshi Kuwabara

unread,
Feb 24, 2014, 1:31:53 AM2/24/14
to node...@googlegroups.com

zlibモジュールでは直接ディレクトリの解凍はできまでんでしたね。

Streamインターフェースではないですが、adm-zipというモジュールだと解凍できました。

meganetops

unread,
Feb 24, 2014, 2:29:45 AM2/24/14
to node...@googlegroups.com
Hiroshi Kuwabara 様

ありがとうございます。
adm-zipで無事に解決できました!
最終的には下記のようなコードにしてみました。

var http = require("http");
var fs = require("fs");
var AdmZip = require('adm-zip');

var savedir  = "./tmp"
var unzipdir = savedir+"/wp";
var zipdir   = savedir+"/wordpres-latest.zip";
var output   = fs.createWriteStream(zipdir);

var req = http.get(url,function(res){
res.pipe(output);
res.on("data",function(){
console.log("on-data・・・");
});
res.on("end",function(){
console.log("finish!!!!!!!!");
output.close();
});
});

output.on("close",function(){
console.log("close!!!!!!!!");
setTimeout(function(){
// setTimeoutでタイミングをずらさないと下記のエラー
//Invalid or unsupported zip format. No END header found
console.log("setTimeout!!!!!!!!");
var zip = new AdmZip(zipdir);
zip.extractAllTo(unzipdir,true);
},1000);
});

zipデータをダウンロードさせた後、すぐに解凍しようとするとエラーが出てしまったので、
setTimeoutで少しタイミングをずらしてみると回避できました(汗
きちんとした方法ではないと思いますのでまた時間をとって悩んでみたいと思います。



2014年2月24日月曜日 15時31分53秒 UTC+9 Hiroshi Kuwabara:

Shigeki Ohtsu

unread,
Feb 24, 2014, 3:36:16 AM2/24/14
to node...@googlegroups.com
大津です。

zlib の Unzip って、 gzip か deflate かを自動的に判別して解凍する
メソッドで、zip ファイルエンコーディングされたものを扱うわけじゃ
ないんですよね。紛らわしいので注意が必要です。

setTimeoutの件は、時間をとって悩みたいということなので解答は書きませんが、
おそらくOSのファイルバッファにまだたまっていてディスクへの書き込みが完了
してからでないでしょう。
fs のマニュアルをよく読んで解決策を探してみましょう。

またメモリを使っていいなら、わざわざファイルに書き出さず
Buffer使って zip 展開できます。

https://gist.github.com/shigeki/01814e5e771c00a82a97

これなら(多少速いし)setTimeout に悩まなくてすみますよ。
> https://github.com/cthackers/adm-zip <https://github.com/cthackers/adm-zip>
>
>
>
> On Saturday, February 22, 2014 6:09:45 PM UTC+9, meganetops wrote:
>
> node組込みのzlibモジュールにチャンレンジしてみました。
> http://nodejs.jp/nodejs.org_ja/docs/v0.10/api/zlib.html <http://nodejs.jp/nodejs.org_ja/docs/v0.10/api/zlib.html>
> あと、zipの展開には「node-unzip <https://github.com/EvanOxfeld/node-unzip>」というものを使用させていただいております。
>
> 下記のコードで動かしてみているのですが何が原因となっていますでしょうか?
>
> |
> var http = require("http");
> var fs = require("fs");
> var unzip = require("unzip");
>
> var url = "http://ja.wordpress.org/latest-ja.zip <http://ja.wordpress.org/latest-ja.zip>";
> var savedir = "./tmp"
> var output = fs.createWriteStream(savedir+"/wordpres-latest.zip");
>
>
> var req = http.get(url,function(res){
> res.pipe(output);
>
> res.on("data",function(){
> console.log("on-data・・・");
> });
> res.on("end",function(){
> console.log("finish!!!!!!!!");
> output.close();
> fs.createReadStream(savedir+"/wordpres-latest.zip")
> .pipe(unzip.Extract({ path: savedir }))
> .on('error', function (err) { console.log('error', err); })
> .on('close', function () { console.log('closed'); });
> });
> });
> |
>
> zipの解凍はできているようで、
> 展開されたファイルは出てきています。
>
> よろしくお願いいたします。
>
>
> --
>
> ---
> このメールは Google グループのグループ「Node.js 日本ユーザグループ」の登録者に送られています。
> このグループから退会し、メールの受信を停止するには、nodejs_jp+...@googlegroups.com にメールを送信します。
> その他のオプションについては、https://groups.google.com/groups/opt_out にアクセスしてください。

Reply all
Reply to author
Forward
0 new messages