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

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

ただいまの
回答率

91.24%

  • PHP

    15718questions

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

  • サーバ

    655questions

    サーバは、 クライアントサーバモデルにおいてクライアントからの要求に対し 何らかのサービスを提供するプログラムを指す言葉です。 また、サーバーソフトウェアを稼動させているコンピュータ機器そのもののことも、 サーバーと呼ぶ場合もあります。

  • zip

    41questions

    ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。

ZipArchive使用時のタイムアウト

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 92

Zu_Chan

score 8

実現したいこと

PHP側でリンクをクリックすると、サーバ側のZipArchiveでリアルタイムでディレクトリをZip化し、ダウンロードしたいと考えています。
現状でわかっていることが、Zip化したいディレクトリが画像を扱うので、フォルダサイズが大きくなりZip化に時間がかかっているということです。

実行⇒Zip化開始⇒ブラウザ側タイムアウト⇒Zip化終了
という状態を確認できています。

このタイムアウトを回避したいです。

ソース

<?php
namespace My;

//処理制限時間を外す
set_time_limit(0);

/**
 * ZipArchiveを拡張して、ディレクトリまるまる扱う機能を追加
 */
class MyZipArchive extends \ZipArchive
{
    /**
     * ディレクトリをまるごとzipファイルにします。
     *
     * @param string $dir              ディレクトリパス
     * @param string $inner_path       zipファイル中のディレクトリパス
     * @param bool   $create_empty_dir 空ディレクトリもディレクトリを作成するか
     * @return bool  処理の成否
     */
    public function addDir($dir, $inner_path, $create_empty_dir=false){
        $items = \array_diff(\scandir($dir), ['.','..']);
        $item_count = \count($items);

        if($create_empty_dir || $item_count > 0){
            $this->addEmptyDir($inner_path);
        }

        // 追加するものがないならここで終了する
        if($item_count === 0) return true;


        foreach($items as $_item){ // forで行うなら$itemsは一旦array_values()を通したほうがいい
            $_path = $dir . DIRECTORY_SEPARATOR . $_item;
            $_item_inner_path = $inner_path . DIRECTORY_SEPARATOR . $_item;

            // ディレクトリの場合は再帰的に処理する
            if(\is_dir($_path)){
                $_r = \call_user_func( // "$this->addDir"より保守的に好ましい
                    [$this, __FUNCTION__], $_path, $_item_inner_path);
                if(!$_r) return false;
            }
            // ファイルの場合でかつ処理に失敗したときはこちら
            else if(!$this->addFile($_path, $_item_inner_path)
                  && !$this->on_recursive_error($dir, $inner_path, $create_empty_dir)){
                return false;
            }
            // ファイルの追加成功時は何も他には行わない
        }

        return true;
    }

    /**
     * 再帰的処理のときにエラーが生じたらどうするかを定義しています。
     *
     * @param string $parent_dir              ディレクトリパス
     * @param string $parent_inner_path       zipファイル中のディレクトリパス
     * @param bool   $create_empty_dir        空ディレクトリもディレクトリを作成するか
     * @return bool Falseならその場で中断
     */
    private function on_recursive_error($parent_dir, $parent_inner_path, $create_empty_dir){
        // 自由に定義してください
        return false;
    }
}


/*
 * 下記は、質問本文のコードをちょっと改造してのテスト
 */

//Zipクラスロード
$zip = new MyZipArchive();

//Zipファイル名指定
$zipFileName = '***.zip';

//Zipファイル一時保存ディレクトリ取得
$zipTmpDir = './';

// Zipファイルのパス
$zip_file = $zipTmpDir . DIRECTORY_SEPARATOR . $zipFileName;

//Zipファイルオープン
$result = $zip->open($zip_file, \ZIPARCHIVE::CREATE | \ZIPARCHIVE::OVERWRITE);

if ($result !== true) {
    return false;
}


// ※今回の肝
$zip->addDir('csv', 'csv', true);
$zip->addDir('images', 'images', true);

$zip->close();


// ストリームに出力
header('Content-Type: application/zip; name="' . $zipFileName . '"');
header('Content-Disposition: attachment; filename="' . $zipFileName . '"');
header('Content-Length: '.filesize($zip_file));
echo file_get_contents($zip_file);

// 一時ファイルを削除しておく
unlink($zip_file);
exit();
?>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

えっと、非同期通信します。

まず、非同期でZip圧縮処理を叩いて、バックグラウンドで圧縮処理を走らせます。
その圧縮処理では進行状況をログに出力します。

一方、別の非同期通信で、さっきのログを読んで圧縮が終わったか確認し続けます。
圧縮が終わっていたら、晴れて、ファイルをダウンロードします。

以上ですん。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

ただいまの回答率

91.24%

関連した質問

同じタグがついた質問を見る

  • PHP

    15718questions

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

  • サーバ

    655questions

    サーバは、 クライアントサーバモデルにおいてクライアントからの要求に対し 何らかのサービスを提供するプログラムを指す言葉です。 また、サーバーソフトウェアを稼動させているコンピュータ機器そのもののことも、 サーバーと呼ぶ場合もあります。

  • zip

    41questions

    ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。