忍者ブログ

カウンター

プロモーション

カレンダー

04 2024/05 06
S M T W T F S
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

AntinomyMy の実験室

   私のWEBアプリ実験室です!

ブログ内検索

楽天でお買い物

twitter

最新トラックバック

最新コメント

忍者アナライズ

ウェザーニュース

バーコード

本を買う

アクセス解析

Google+

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


  • 2024/05/04 00:55

PHPの挙動が環境で変化する問題(ZipArchive編)

PHP の調べ物

メモでーす^^;

PHPでZIPファイルを作る処理、
これでZIPファイル名がおかしかったので、これを取り上げる。

具体的には、img_xxx.zip.何らかの文字列
みたいになるので、何が原因か?

それを調べようと思い、テストソースを書いてみた。

思っていた事とは違ったが、Linuxのサーバーと
Windows のサーバーで挙動が違うので載せることにした(メモだけど)。

勿論、PHPのバージョンにも大きく関係しているが、
どのバージョンでもできるだけ共通に書ける事が望ましいので、
バージョンどうこうというよりも、こうなるとこうなった!という内容だけを記述してみる。

<?php
 
$openFile = 'img_001.zip';
 
$fp_debug = fopen($openFile, 'a+'); //指定のパスのファイルネームがあれば追記モードで開き、無ければ作成
$zip = new ZipArchive();
$zip2 = new ZipArchive();
$rs = $zip->open($openFile, ZIPARCHIVE::CREATE); //
$rs2 = $zip2->open($openFile, ZIPARCHIVE::CREATE); // | ZIPARCHIVE::OVERWRITE
if($rs === TRUE){
echo 'ZIPオープン';
    $zip->addFromString('test.txt', 'ここにファイルの内容を書きます');
$zip->close();
}else{
echo 'ZIPエラーミス';
}
if($rs2 === TRUE){
echo 'ZIP2オープン';
    $zip2->addFromString('test2.txt', 'ここにファイルの内容を書きます2');
$zip2->close();
}else{
echo 'ZIP2エラーミス';
}
 
echo "<br>\r\nZIPの中身<br>\r\n";
$zip3 = new ZipArchive();
if ($zip3->open($openFile) == TRUE) {
for ($i = 0; $i < $zip3->numFiles; $i++) {
echo "No$i:". $zip3->getNameIndex($i)."<br>\r\n";
}
}
 
fclose($fp_debug);
 
?>

これをLinux、Windows の環境で実行すると、img_001.zipファイルは両方とも出来るのは確認できる、
しかしWindows環境で、1回目の実行でファイルを作ったPCのディレクトリを見れば確認できるが、
zip3のオブジェクトで中身を表示するルーチンの部分(ブラウザ閲覧)ではすぐに確認が取れない。

結局Windows では、ブラウザをリロードした2度目の実行でzip3のオブジェクトでの確認ができる・・・
Linux は1度目からリロードせずに確認できる、これもかなり変な感じだが、
それは適当にロックが?!?!?!?!?と予想して、後回しにして(なぜ?とか言わないでネ!゜w゜; 眠いのですw)、
そして先にこれ以前に大きな違いが作られたファイルに見られた。

Windows環境の方では、「test.txt」のみが作られ
Linux環境では、「test2.txt」のみが作られたのを確認した。

とりあえず、ファイルをロックして、使っている状態でfopenでロックしたつもりであったが、
そんなのお構いなしで、ZIPファイルの作成処理に入ってしまっている。

結局私が知りたかった、
img_003.zipのファイルを追加したり消したりしていると、
img_003.zip.7Cnqxd というファイルネームが出来る原因が掴めなかった(追伸:--- 追伸の追伸 ---、ブログ後半以降で解決?)。

元々自分が作ったプログラムを修正しているのではないので、
毎回何が悪いんだろう;w;?と思いながら、あれこれやってみて、
おかしな挙動に気がついたりする。


今回、なんとなくわかった事は、ZIPファイルのロックや、重複オープンで、仕方なしに別名でZIPファイルを作成した為に、
 名前が変わっているのでは無さそうだ・・・・)


個人的なメモでした<_ _> お粗末!


---追伸---
なんか、ZIPファイルを作る時と、消すときのファイルネームの取得の仕方が違い、
なんか怪しいプログラムだったので(私が作ったのではない・・・)、
ZIPのファイルを->open($openFile) する時には、そのオープンするファイルが存在するか?
のルーチンを付け足したら、なぜか変なZIPファイル名のimg_003.zip.7Cnqxd が出来なくなった・・・
うーん・・・・・ よく分からない情報元からループしてファイル名を取得しているので、
その大本も怪しい

とりあえず、何を付加えたか?

if(file_exists($z_name)){ //ファイルが無いのに開こうとうすると、作られてしまうのを防ぎたい

というのを->open($openFile) が使われる前に行い、
一連のZIPファイルの内容をその判断(file_exists関数でファイルがあるかどうか)の中にいれたら
なぜか解決しました?!

実は違うファイル名で、無いファイルでも開こうとすると、新たしいZIPのファイルが出来てしまうので、
これが原因?だったのかな?と思っています・・

本当にスパゲティープログラム(変数名を何度も再利用して、途中で初期化とかする、関数化しないプログラム、
何度も同じルーチンが出現するけれど、全く同一かどうか、確認しないといけないプログラム、などなど)を
見て欲しいとか、どんだけ時間かかると思っているんだ!とか言いたくなるんですorz

同じ注文でも、中身によっては全く違うって事を同じ世の人に知ってもらいたかったりするw

長文のやった事、忘れない為のメモでした^^;ノシ

--- 追伸の追伸 ---

本当のバグがわかった!
複数の要求で、->open が書かれたファイルを同時に走らせて、
しかもinclude しているファイルの中にも->open 関数があった!

それで、よく見ると->closeが->open をした時の成功、不成功の判断で
->close をしていなくて、何の条件もなしに->close をしていた。

つまり、->open しなくともclose しているので、それで何かを閉じしまう可能性が、
何らかのバグなのであるかもしれないと思った。

どちらにしても、そこでエラーにもなるだろうから、
とりあえず、->open している時のみ、->close する様に、->open の戻り値で開いた場合のみ、
->close する様に修正した。

あと、サーバーやローカルサーバーの処理が多くなると、
zipの一時ファイルがほんの一瞬でも目に止まるまで、作成や削除のスピードが遅れ、
目に付く様になる気がした(Windows 7環境)。
どちらにしてもバグを持っているのは、Linux 環境※のみ※であるという、
不可解な状況なのだけれど、
opendir でZIPファイルを探して、そのファイルを処理などするときに、
zipの一時ファイルがあると、これに追加(削除も?)処理をしてしまい、
処理を施してしまうと、自動で一時ファイルが消えない様だ。

なので、名前を確認する必要がある(あった)。

img_数値.zip なのだが、これが・・・・
実例:
img_005.zip.lCyKob
img_005.zip.mdCkcu
img_005.zip.hj9NcF
img_005.zip.xcNUYx
img_005.zip.MK7cZG
img_006.zip.CSbPq9
img_006.zip.iWWGZc
img_006.zip.G3soMF
img_006.zip.T9tntU
img_006.zip.B2divg
などと、一時ファイルが出来てしまうのを確認している。

ここでちょっと公式のマニュアルにない仕様が、やはり明らかにある事を感じた。
それは、ZIPファイルの一時処理用のファイルが作成され、それは元の名前+αという仕様である。
公式マニュアルに載せておいてほしい・・・・ これでどれだけの時間を潰したやら・・・・

なので、しっかり対象のimg_数値.zip を探る様に
正規表現を使って、余計な文字があったかどうかを確かめる必要がある。

例えば
if('' != preg_replace("/^img_\d+\.zip/",'',$zf))
で、img_数値.zip を取り除いた後に、空白でなかったら・・・・ このファイルが違うので、他の処理をするなどです。

初めは空白出なかった時に、この一時ファイルを強制的にunlink を使って消そうとしていたけれど、
もしかして、これは放置していれば、そしてしっかりclose などがされていれば、消えるんじゃないだろうか?
と思い、unlink 関数をせずに放置をしていた所、やはり自動でうまく消えてくれる様であった。

私が作ったソースでない為・・・close が->open の戻り値で判断されていないのに無いのに気がつくのに時間がかかった;x;

多分、もう消す処理はしないので
!= でなく == にして
if('' == preg_replace("/^img_\d+\.zip/",'',$zf))
と書いて、{}内に正常な時として処理を加えれば通常は問題ない

ただ、デバッグのトラップとして、そのおかしな一時ファイルの名前を知りたい時は
== でなくて != にしておけばそこでそのファイル名を知ることが出来る。


あぁー なんでこんな得たいのしれないスパゲティーのソースを解析しないといけないんだろうと思いつつ、
眠くて仕方ないので、寝る事にする@x@;

もうなんか、眠くて何を言っているのか分からなくなっているので、後で見直すかも(かもですw)、
付加えとか、付加えとか、付加えとか、きっと多分あったりなかったりします(謎)


長文で失礼! お粗末でした<_ _>

拍手[0回]

PR


  • 2013/08/08 03:22

コメント一覧

  • お名前
  • Email

  • コメント

  • Vodafone絵文字 i-mode絵文字 Ezweb絵文字
  • パスワード
[PR]