質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

5921閲覧

Windows環境 ZipArchive 解凍

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2016/07/27 02:42

編集2016/07/27 02:52

###前提・実現したいこと
windows環境でzipを解凍したいです。
現在ZipArchiveで作成したZipをエクスプローラーから解凍したいのですが、
出来ないでいます。macで動作を確認した時には解凍が出来たのですがWindowsでやるとうまくいきません。似たような事例で英語ですが

http://stackoverflow.com/questions/4620205/php-ziparchive-corrupt-in-windows

上記の問題と似ている気がします。しかし英語が不慣れで理解が難しく問題解決が出来ないでいます。何卒よろしくお願いします。
###発生している問題・エラーメッセージ
Windows環境での解凍ができません エクスプローラーで開くと無効と表示されます。
###該当のソースコード

php

1define("file-path","C:MAMP/htdocs/fileup/test/"); 2 3//圧縮するファイル指定 4$dir = file-path; 5// Zipファイルの保存先 6$file = "./Zipfile/" . date("his") .'.zip'; 7$root = ""; 8zipDirectory($dir, $file,$root); 9} 10function zipDirectory($dir, $file, $root){ 11$zip = new ZipArchive(); 12//$fileにZipを作成する読み込み/書き込み/変更用にオープンします。 13$res = $zip->open($file, ZipArchive::CREATE); 14if($res){ 15// $rootが指定されていればその名前のフォルダにファイルをまとめる 16if($root != "") { 17//空のディレクトリを追加 18$zip->addEmptyDir($root); 19$root .= DIRECTORY_SEPARATOR; 20} 21//文字数カウント 22$baseLen = mb_strlen($dir); 23//RecursiveIteratorIterator()とRecursiveDirectoryIterator()を組み合わせると、再帰関数を利用 24$iterator = new RecursiveIteratorIterator( 25new RecursiveDirectoryIterator( 26$dir, 27FilesystemIterator::SKIP_DOTS //隠しファイルをスキップ 28|FilesystemIterator::KEY_AS_PATHNAME //パス名を返す 29|FilesystemIterator::CURRENT_AS_FILEINFO //ファイルの拡張子を取得 30), RecursiveIteratorIterator::SELF_FIRST //(親から先に) 取り上げます。 31); 32 33//順番に配列に入れていく 34foreach($iterator as $pathname => $info){ 35//$pathnam が実際に圧縮したい対象 36$localpath = mb_substr($pathname, $baseLen); 37if( $info->isFile() ){ 38$zip->addfile($pathname, $localpath); 39} else { 40$res = $zip->addEmptyDir($localpath);} 41} 42$zip->close(); 43} else { 44return false; 45} 46header('Content-Type: application/zip'); 47header(sprintf('Content-Disposition: attachment; filename="%s"',basename($file))); 48header(sprintf('Content-Length: %d', filesize($file))); 49readfile();

###試したこと
headerをzipに指定、macでの動作確認はできました。
###補足情報(言語/FW/ツール等のバージョンなど)
MAMP windows10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kunai

2016/07/27 03:11

コードは見てませんが、上記英文サイトの英文を見ると、 ・ファイルの先頭のスラッシュを削除しろ とありますね。
退会済みユーザー

退会済みユーザー

2016/07/27 03:46

$file = "./Zipfile/" . date("his") .".zip";を修正してしますとファイル名が変わってしまいました。また、 試しに$file = "./Zipfile/" . date("his") .'.zip';を$file = ".Zipfile/" . date("his") .'.zip'; にして$root .= DIRECTORY_SEPARATORをコメントアウト にしてみましたが、変わりませんでした。 また、記述方法が正しいかはわかりませんが文字列を抽出する場所に $localpath = mb_substr($pathname, $baseLen,ltrim($pathname, '/')); と記載してみましたが変わりませんでした。
guest

回答3

0

リンク先の二番目の回答を翻訳します。

I had this same problem, and my solution was similar to the correct answer on this thread. When you put a file in the archive, you can't have absolute files (files starting with a slash) or else it won't open in Windows for some reason.
私も同じ問題に出遭いました。私の解決法は、このスレッドの正しい回答と同じでした。アーカイブにファイルを入れる時、絶対パス(スラッシュで始まるパス)を入れてはいけません。でないと、何かの理由でウィンドウズでは開けなくなります。

So got it working not because he (Jesse Bunch, the selected answer at the time of this writing) removed the containing folder but because he removed the starting slash.
だから、彼(Jesse Bunch さん、これを書いている時点でのベストアンサー)がうまくいったのは、フォルダを外したからではなく、始めのスラッシュを外したからです。

I fixed the issue by changing
私はこの問題を次のように解決しました。

PHP

1$zip->addFile($file, $file); // $file is something like /path/to/file.png

to

PHP

1// we make file relative by removing beginning slash so it will open in Windows 2$zip->addFile($file, ltrim($file, '/'));

に変えて。
and then it was able to open in Windows!
そうするとウィンドウズで開けるようになりました!

That's probably the same reason pclzip (Plahcinski's answer) works. I bet it automatically strips off the beginning slash.
Plahcinski さんの回答の pclzip がうまくいくのも恐らく同じ理由です。それは自動的に始めのスラッシュを外しているんだと断言します。

投稿2016/07/27 03:06

編集2016/07/27 03:10
Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/07/27 03:13

ありがとうございます。 試しに$file = "./Zipfile/" . date("his") .'.zip';を$file = "Zipfile/" . date("his") .'.zip'; にして$root .= DIRECTORY_SEPARATORをコメントアウト にしてみましたが、変わりませんでした。 また、記述方法が正しいかはわかりませんが文字列を抽出する場所に $localpath = mb_substr($pathname, $baseLen,ltrim($pathname, '/')); と記載してみましたが変わりませんでした。
Zuishin

2016/07/27 03:19

mb_substr の使い方間違ってませんか? $pathname = ltrim($pathname, '/') としてから改めて $baseLen を取得し、mb_substr($pathname, $baseLen) ではありませんか?
退会済みユーザー

退会済みユーザー

2016/07/27 03:51

ご指摘ありがとうございます。 foreach($iterator as $pathname => $info){ //$pathnam が実際に圧縮したい対象 $pathname = ltrim($pathname, '/') $localpath = mb_substr($pathname, $baseLen); if( $info->isFile() ){ $zip->addfile($pathname, $localpath,"SJIS", "UTF-8"); } else { $res = $zip->addEmptyDir($localpath,"SJIS", "UTF-8"); } } $zip->close(); } else { return false; } このように記述してみますとエラーが排出されます。 Parse error: syntax error, unexpected '$localpath' (T_VARIABLE) in C:\MAMP\htdocs\upload\upload-file.php on line 150 希望している記述とちがいましたらおっしゃっていただけると嬉しいです。
Zuishin

2016/07/27 03:56

とりあえずセミコロンがありません。あとbaselen を計算していません。
退会済みユーザー

退会済みユーザー

2016/07/27 04:14

失礼しました。 foreach($iterator as $pathname => $info){ $pathname = ltrim($pathname, '/'); $baseLen = mb_strlen($dir); //$pathnam が実際に圧縮したい対象 $localpath = mb_substr($pathname, $baseLen); if( $info->isFile() ){ $zip->addfile($pathname, $localpath); } else { $res = $zip->addEmptyDir($localpath); } } $zip->close(); } else { return false; } $dirで取った文字数とは別で取得し、対象を$dirではなく$localpathにすべきでしょうか?
guest

0

ファイル名の拡張子は .zip になってますか?

(と、まずは基本的なことから確認)

投稿2016/07/27 02:55

takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/07/27 02:57

ご回答ありがとうございます。 はい、プロパティを確認したところ、圧縮 (zip 形式) フォルダー (.zip)になっています。
guest

0

ベストアンサー

無事解決できました。
ストリーム出力の際にreadfile($file);の前にmb_http_output("pass");を入れることで
readfile()の結果のバイナリをPHPが勝手に自動変換して壊してしまうことを防ぐみたいです。
私自身つぎはぎで作っていたので理解が乏しくご迷惑をおかけしました。
下記に変更したheaderを載せます

header('Content-Type: application/zip');
header(sprintf('Content-Disposition: attachment; filename="%s"',basename($file)));
header(sprintf('Content-Length: %d', filesize($file)));
mb_http_output("pass");
readfile($file);

ありがとうございました。

投稿2016/07/27 04:23

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問