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

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

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

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

Q&A

解決済

2回答

6662閲覧

ディレクトリをまるごとZipで圧縮して、ダウンロードさせたい。

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

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

0グッド

0クリップ

投稿2015/08/13 13:44

PHPで、ディレクトリをまるごとZipで圧縮してダウンロードさせる仕組みを作りたいです。

リンクをクリックすることでZipで圧縮されたフォルダをダウンロードさせいたいのですが、
いくつかのサイトを参考にさせてもらったにも関わらず理解することが出来ませんでした。

現在は、中身がファイルのみであれば、Zipで圧縮してダウンロードさせることは可能です。

ディレクトリは以下のような構成のものを圧縮したいです。

test.zip
|-images
|-image1.jpg
|-image2.jpg
|-file1.php
|-file2.php

複数ファイルの入ったフォルダと、ファイルが複数枚といった構成です。

ディレクトリを階層ごと圧縮するには再帰的な処理が必要とのことなのですが、
いまいち理解ができていません。

参考になるサイト、追加すべき情報、プログラムの組み方などありましたらお教え下さい。
サンプルプログラムのような物でも構いません。

自分の使っている、中身がファイルのみでのZipで圧縮するプログラムを載せておきます。

PHP

1<?php 2//Zipクラスロード 3$zip = new ZipArchive(); 4 5//Zipファイル名指定 6$zipFileName = 'test.zip'; 7 8//Zipファイル一時保存ディレクトリ取得 9$zipTmpDir = '/phpdocs/filelesson'; 10 11//Zipファイルオープン 12$result = $zip->open($zipTmpDir.$zipFileName, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE); 13 14if ($result !== true) { 15 return false; 16} 17 18//処理制限時間を外す 19set_time_limit(0); 20 21//パス 22$fpath_array = array('images/asn.jpg','images/asn2.jpg','images/shirika.jpg'); 23 24//Zip追加処理 25foreach ($fpath_array as $filepath) { 26 //filename取得 27 $filename = basename($filepath); 28 29 //取得ファイルをZipに追加ccccccc 30 $zip->addFromString($filename,file_get_contents($filepath)); 31} 32 33$zip->close(); 34 35// ストリームに出力 36header('Content-Type: application/zip; name="' . $zipFileName . '"'); 37header('Content-Disposition: attachment; filename="' . $zipFileName . '"'); 38header('Content-Length: '.filesize($zipTmpDir.$zipFileName)); 39echo file_get_contents($zipTmpDir.$zipFileName); 40 41// 一時ファイルを削除しておく 42unlink($zipTmpDir.$zipFileName); 43exit();

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

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

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

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

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

guest

回答2

0

投稿2015/08/14 06:34

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2015/08/14 06:53

ご回答ありがとうございます。 そちらのサイトは既に拝見させて頂いたのですが、理解することが出来ませんでしたのでこちらで質問をさせて頂いております。 ただ、サイトに記述されている方法で私のやりたい事ができていることは事実ですので、今一度しっかりとサイトの方も確認し直しておきたいと思います。
退会済みユーザー

退会済みユーザー

2015/08/14 07:01

> そちらのサイトは既に拝見させて頂いたのですが、理解することが出来ませんでしたのでこちらで質問をさせて頂いております。 それならそれと言ってくれれば…。 具体的にわからないところを聞けばいいと思いませんか?
退会済みユーザー

退会済みユーザー

2015/08/14 07:40

分かりづらくてすみません。 「いくつかのサイトを参考にさせてもらったにも関わらず理解することが出来ませんでした。」「ディレクトリを階層ごと圧縮するには再帰的な処理が必要とのことなのですが、 いまいち理解ができていません。 」 と、本文に記載してあるとおり、いくつかのサイトは参考にさせていただいております。 また分からない所に関しましても、ディレクトリをまるごと圧縮するための再帰的な処理といったものが具体的にどういったものなのかが理解できないという意味になります。
退会済みユーザー

退会済みユーザー

2015/08/14 08:05 編集

サンプルコードは一度試したんでしょうかね…。 サブディレクトリの中のファイルを作成するには、最終の階層までファイルを探索してZIPにして行きましょうって話ですけど。 funcName(){ funcName(); } のように関数の中から自分自身の関数を呼び出すことを再帰処理と言います。
退会済みユーザー

退会済みユーザー

2015/08/14 07:53

Javaの場合、Zipファイルに追加するときのパスにディレクトリが含まれていれば、ディレクトリとして扱います。PHPだと異なるのでしょうか? ところで再帰的な処理というのは「ファイルツリーをたどってファイルを追加する」のことでしょうか?例えば、下記の処理を行ったとすると、ディレクトリを辿る処理を再帰的に呼び出していますよね? ### ディレクトリを辿る処理 1. ディレクトリ内の要素を全て取得する - ディレクトリ内の要素は、「ファイル」か「ディレクトリ」 2. それぞれの要素を処理する 2.1 取得した要素がファイルであればZipに追加する 2.2 取得した要素がディレクトリであれば、そのディレクトリを対象に「ディレクトリを辿る処理」を呼び出す
退会済みユーザー

退会済みユーザー

2015/08/14 08:00

そうです。その解釈であってますよ。
退会済みユーザー

退会済みユーザー

2015/08/14 08:15 編集

ただし、紹介したサイトの方法では、再帰的なファイルツリーの探索を RecursiveIteratorIterator が行っています。 http://php.net/manual/ja/class.recursiveiteratoriterator.php 紹介したサイトのコードをそのまま実行したら、それで動くんですけどね…
退会済みユーザー

退会済みユーザー

2015/08/14 08:29 編集

ありがとうございます。 サンプルコードはサイトを最初に拝見させていただいた時に実行しています。 しかし、例外が投げられて動かないので困っていました。 RecursiveIteratorIteratorに関しても、Kosuke_Shibuya様が貼られているページで確認はしましたが、自分では何が書いてあるのかさっぱりでした。 Konpiro様が指摘してくださったaddFile()メソッドを試させていただいた結果、 test.zip   |-images     |-image1.jpg     |-image2.jpg といった形まではできましたが、test.zipの直下にファイルを置くことが出来ずに困っているのが現状になります。
退会済みユーザー

退会済みユーザー

2015/08/14 08:40 編集

> 例外が投げられて動かないので困っていました。 具体的に書いてくれないと、こちらでは発生しないので、そのまま書いてください。 > RecursiveIteratorIteratorに関しても イテレータについては、デザインパターンを理解していないときついかも… そこの理解は後でもいいと思いますよ。
退会済みユーザー

退会済みユーザー

2015/08/14 08:52

ありがとうございます。 Fatal error: Uncaught exception 'UnexpectedValueException' with message 'RecursiveDirectoryIterator::__construct(C:\phpdocs\filelesson/base/,C:\phpdocs\filelesson/base/): ' in C:\phpdocs\filelesson\file_dw_4.php on line 31 と出ています。 file_dw_4.phpにサンプルコードをそのまま、何も手を付けずにコピペしてあります。
退会済みユーザー

退会済みユーザー

2015/08/14 09:10 編集

コードと合わせて書いてください。 > file_dw_4.phpにサンプルコードをそのまま、何も手を付けずにコピペしてあります。 私の手元にfile_dw_4.phpはありません。 なるほど、わかった。 サンプルコードではディレクトリのセパレータは「/」ですが、あなたの環境はwindows のようですので、「\」ですね。 ’C:\phpdocs\filelesson/base/’ ← ここおかしいのはわかると思います。
退会済みユーザー

退会済みユーザー

2015/08/14 09:13

Windows では「\」円マーク、LInux, Mac では「/」になります。 テスト環境でwindows 本番環境でLinux などの場合、一歩ではこけてしまうので 通常、DIRECTORY_SEPARATOR を使用します。
退会済みユーザー

退会済みユーザー

2015/08/14 22:05

環境によって違うことを知りませんでした。 直すべき場所や知るべき知識が少しずつ分かってきましたので、今一度自分でしっかりと勉強して挑戦していきたと思います。 長々とお付き合いいただき、ありがとうございました。
guest

0

ベストアンサー

あまりPHPについては詳しくないのですが、コードを読んでいて「あれ?」と思った点を書きます。

PHP

1//取得ファイルをZipに追加ccccccc 2$zip->addFromString($filename,file_get_contents($filepath));

とされていますが、画像などバイナリファイルを文字列として扱えないのではないでしょうか?
(もしかしてPHPだと扱えたりしますか?)

ZipArchiveクラスのドキュメントを読んでみると、addFile()というメソッドが見つかりました。

filepathがあるので、下記のようにしてみるとどうなるでしょうか?

PHP

1//取得ファイルをZipに追加ccccccc 2$zip->addFile($filepath);

投稿2015/08/13 16:23

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2015/08/14 06:30

ご回答ありがとうございます。 質問が分かりづらくてすみません。 上記のコードは正しく動いているのですが、このやり方だとファイルのみの圧縮になってしまい、フォルダが圧縮できないという問題と、コードにファイルパスを直接書かなければならないといった問題があります。 あくまで「ここまではできています」といった目安で載せておいたものです。 addFile()メソッドについて詳しく調べてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問