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

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

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

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

Q&A

解決済

3回答

8231閲覧

ディレクトリを丸ごとzipでダウンロードしたい

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

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

0グッド

0クリップ

投稿2016/01/14 17:36

編集2016/01/18 01:38

よろしくお願いします。

ディレクトリをまるごとzipでダウンロードしたいです。

Windows8.1
php 5.4.39
Apache 2.2.14
localでの実行です。

ziptest
|
|-mysite
| |-image
| | |-image1.png
| |-file1.php
| |-file2.php
|
|-exe.php(zipに圧縮する処理が書かれたファイル。これを実行する。)

上記が私の環境です。

やりたいことですが、mysiteの中身を丸ごとzipで圧縮してダウンロードをしたいという事です。

mysite
|
|-image
| |-image1.png
|
|-file1.php
|-file2.php

上記のような状態のものを、zipで圧縮してダウンロードすることが目標です。

現状ですが、

mysite/image(imageフォルダ)を消した場合、
(以下、パターン1)
mysite.zip
|
|-mysite
| |-file1.php
| |-file2.php
|
|-file1.php
|-file2.php

このような形でzipが出来上がりました。

ちなみに、

$zip->addFromString($filename,file_get_contents($filepath));
こちらをコメントアウトした状態で実行すると、
(以下、パターン2)
mysite.zip
|
|-mysite
| |-file1.php
| |-file2.php

このような形でzipで出来上がります。

どちらにせよ、imageフォルダが存在していると圧縮が出来ません。
どこが原因になっているのでしょうか?

以下にコードを記載します。

php

1<php 2 3//Zipクラスロード 4$zip = new ZipArchive(); 5 6//Zipファイル名指定 7$zipFileName = 'mysite.zip'; 8 9//Zipファイル一時保存ディレクトリ取得 10$zipTmpDir = '/phpdocs/nonprothemes'; 11 12//Zipファイルオープン 13$result = $zip->open($zipTmpDir.$zipFileName, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE); 14 15if ($result !== true) { 16 return false; 17} 18 19//処理制限時間を外す 20set_time_limit(0); 21 22 23/* ファイルパスを指定する処理 */ 24 25//mysite内のファイル一覧取得 26//ディクトリパス格納用変数 27$dir = null; 28$dir = 'mysite/'; 29 30//ハンドル取得用変数 31$handle = null; 32//ファイル情報取得用変数 33$file = null; 34//ファイルパス指定用配列 35$fpath_array = array(); 36 37//ディレクトリの存在確認、ハンドル取得 38if(is_dir($dir) && $handle = opendir($dir)) 39{ 40 //ディレクトリ内のファイルを取得 41 while(($file = readdir($handle)) !== false) 42 { 43 //'.','..'を取り除く処理 44 if($file != "." && $file != "..") 45 { 46 //ファイルパス指定 47 $fpath_array[] = 'mysite/'.$file; 48 } 49 } 50} 51 52//ファイルパス指定 53//$fpath_array = array('mysite/style.css','mysite/index.php'); 54/* ここまで */ 55 56//Zip追加処理 57foreach ($fpath_array as $filepath) { 58 //filename取得 59 $filename = basename($filepath); 60 61 //取得ファイルをZipに追加 62 $zip->addFromString($filename,file_get_contents($filepath)); 63 $zip->addFile($filepath); 64} 65 66$zip->close(); 67 68// ストリームに出力 69header('Content-Type: application/zip; name="' . $zipFileName . '"'); 70header('Content-Disposition: attachment; filename="' . $zipFileName . '"'); 71header('Content-Length: '.filesize($zipTmpDir.$zipFileName)); 72echo file_get_contents($zipTmpDir.$zipFileName); 73 74// 一時ファイルを削除しておく 75unlink($zipTmpDir.$zipFileName); 76?>

どこが原因になっているでしょうか?
よろしくお願いします。

/********* 追記 **********/
回答してくださった方の意見を元に、コードを修正しました。
結果、中身の無いzipが出来上がりました。
ただ、zipフォルダはサイズが8KBあります。
どういう状況なのか見当がつきません。
原因について分かることがあれば意見をお願いしたいです。

php

1$dist = 'mysite.zip'; // 生成する圧縮ファイル名 2$path = './mysite'; // 圧縮するパス 3$zipTmpDir = '/phpdocs/nonprothemes'; // 一時パス 4 5 6$zip = new ZipArchive(); 7$zip->open($zipTmpDir.$dist, ZipArchive::CREATE | ZipArchive::OVERWRITE); 8addZip($zip, $path); 9$zip->close(); 10 11function addZip($zip, $path) { 12 if (is_dir($path)) { 13 $files = array_diff(scandir($path), ['.', '..']); 14 foreach ($files as $file) addZip($zip, "$path/$file"); 15 } else { 16 $zip->addFile($path); 17 } 18} 19 20// ストリームに出力 21header('Content-Type: application/zip; name="' . $dist . '"'); 22header('Content-Disposition: attachment; filename="' . $dist . '"'); 23header('Content-Length: '.filesize($zipTmpDir.$dist)); 24echo file_get_contents($zipTmpDir.$dist); 25 26// 一時ファイルを削除しておく 27unlink($zipTmpDir.$dist);

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

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

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

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

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

guest

回答3

0

ベストアンサー

自己解決することが出来ました。
皆様回答ありがとうございました。

全てのファイルパスを、

圧縮したいフォルダ名/(サブフォルダ名)/ファイル名

このように統一して1つの配列にまとめ、addFileでzipに追加、圧縮という形になっています。
サブフォルダはいくつあっても問題ありませんでした。
空のサブフォルダが存在していてもエラーは出ません。
しかし、圧縮したzipには空のサブフォルダは作られません。
以下がコードです。

php

1<?php 2 3//Zipクラスロード 4$zip = new ZipArchive(); 5 6//Zipファイル名指定 7$zipFileName = 'mysite.zip'; 8 9//Zipファイル一時保存ディレクトリ取得 10$zipTmpDir = '/phpdocs/nonprothemes'; 11$path = './mysite'; 12$path2 = 'mysite'; 13 14//Zipファイルオープン 15$result = $zip->open($zipTmpDir.$zipFileName, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE); 16 17if ($result !== true) { 18 return false; 19} 20 21//処理制限時間を外す 22set_time_limit(0); 23 24//パス取得 25$fpath_array_beta = array_diff(scandir($path), ['.', '..']); 26 27// zip追加する本命のパスを格納する配列 28$fpath_array = array(); 29 30// ディレクトリ判別 31foreach ($fpath_array_beta as $key => $value) { 32 if(is_dir("$path/$value")){ 33 // パス指定 34 $path_sub = "$path/$value"; 35 // サブフォルダ内のファイル名取得 36 $array_beta = array_diff(scandir($path_sub), ['.', '..']); 37 // パスとして取得(元配列に追加) 38 foreach ($array_beta as $key2 => $value2) { 39 array_push($fpath_array,"$path2/$value/$value2"); 40 } 41 }else{ 42 // ファイルの場合はそのまま追加 43 array_push($fpath_array,"$path2/$value"); 44 } 45} 46 47// print "<pre />"; var_dump($fpath_array); print "<pre />"; 48 49//Zip追加処理 50foreach ($fpath_array as $filepath) { 51 $zip->addFile($filepath); 52} 53 54$zip->close(); 55 56// ストリームに出力 57header('Content-Type: application/zip; name="' . $zipFileName . '"'); 58header('Content-Disposition: attachment; filename="' . $zipFileName . '"'); 59header('Content-Length: '.filesize($zipTmpDir.$zipFileName)); 60echo file_get_contents($zipTmpDir.$zipFileName); 61 62// 一時ファイルを削除しておく 63unlink($zipTmpDir.$zipFileName);

投稿2016/01/24 22:05

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

再帰を使って書くとこんな感じです。
$pathにはファイルでもディレクトリでも指定出来ます。

php

1<?php 2$dist = 'test.zip'; // 生成する圧縮ファイル名 3$path = './test'; // 圧縮するパス 4 5$zip = new ZipArchive(); 6$zip->open($dist, ZipArchive::CREATE | ZipArchive::OVERWRITE); 7addZip($zip, $path); 8$zip->close(); 9 10function addZip($zip, $path) { 11 if (is_dir($path)) { 12 $files = array_diff(scandir($path), ['.', '..']); 13 foreach ($files as $file) addZip($zip, "$path/$file"); 14 } else { 15 $zip->addFile($path); 16 } 17}

投稿2016/01/15 01:01

naga3

総合スコア1293

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

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

退会済みユーザー

退会済みユーザー

2016/01/17 22:38 編集

回答ありがとうございます。 試してみたところzipの中身が空の状態だったのですが原因は何が考えられるでしょうか?
guest

0

今、お試し環境が手元に無いので具体的な修正例をご提示出来ませんが・・・

ZipArchiveクラスでディレクトリツリー全体を固めたい場合は、ファイル追加前に都度、親ディレクトリを明示的に追加してやる必要があります。
つまり、今のケースでは image ディレクトリを追加してから image1.png を追加します。

ZipArchive クラス

ですが、ディレクトリ階層が深い場合はとても面倒なので、適材適所でLinuxコマンドを併用する方法がおすすめです。
詳細は下記ページをご参照ください。

PHPからフォルダ構成ごとzip圧縮

投稿2016/01/14 23:54

pi-chan

総合スコア5936

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問