【php】複数選択したファイルをZipにまとめてダウンロードさせる方法

php

「画像やpdfなどのファイルをチェックボックスなどで複数選択して一括ダウンロードさせたい。」といった要望はよくあると思います。例えば、ギャラリーサイトで、複数画像の中で必要画像だけ選択させてダウンロードしてもらいたい、とか。複数の資料をpdfで並べておいて、必要分だけ選択してダウンロードしてもらいたいとか。そういった場合、zip形式のファイルにまとめてダウンロードしてもらうといった方法がよくとられると思うのですが、今回はphpでこれを構築する方法を紹介します。

ちなみにこの記事は、フリーのクリエイターとして10年以上のキャリアの中で、私が実際依頼を受けて組み込んだときのメモを基に作成しており。より実践に近いかたちでノウハウをお伝えできるのではないかと思います。

ファイル構成

サンプルのファイル構成は次になります。
ダウンロードしてもらうファイルはpdfファイルで、それを「pdf」フォルダー内に配置しているイメージで解説します。

├── index.html
├── zip.php
├── pdf
│ ├── pdf1.pdf
│ ├── pdf2.pdf
│ └── pdf3.pdf
└── tmp

Index.html【body外は省略】

<form method="post" action="zip.php">
<ul>
<li>test1<input type="checkbox" name="pdf[]" value="pdf/pdf1.pdf" /></li>
<li>test2<input type="checkbox" name="pdf[]" value="pdf/pdf2.pdf" /></li>
<li>test2<input type="checkbox" name="pdf[]" value="pdf/pdf3.pdf" /></li>
</ul>
<input type="submit" name="send" value="ダウンロード" />
</form>


「ダウンロード」をクリックすると、チェックボックスで選択したファイルがzipにひとつにまとめてダウンロードできる。
ファイルが選択されていない場合は、アクションなし。

phpの書き方

<?php

	if (!empty($_POST["pdf"])){
	// ダウンロードさせたいファイル
	$pdf= $_POST['pdf'];
	$pathAry = array();
	for($i=0; $i<sizeof($pdf); $i++){
    $pathAry[] = $pdf[$i];
    }
	
	// zipのインスタンス作成
	$objzip = new zipArchive($pathAry);
	
	// 一時ファイル(zip)の名前とPath
	$zipName = "file_" . date("Ymds") .'.zip';
	$zipPath = 'tmp/' . $zipName;
	
	// 一時ファイル(zipファイル)を作成
	$result = $objzip->open($zipPath, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE);
	if ($result !== true) {
		echo "err - open zip-file";
		exit;
	}
	
	set_time_limit(0);
	
	// zipに追加
	foreach ($pathAry as $filepath) {
		$filename = basename($filepath);
		$objzip->addFromString($filename, file_get_contents($filepath));
	}
	$objzip->close();
	
	// 出力(ダウンロード)
	header('Content-Type: application/zip; name="' . $zipName . '"');
	header('Content-Disposition: attachment; filename="' . $zipName . '"');
	header('Content-Length: '.filesize($zipPath));
	echo file_get_contents($zipPath);
	
	// 一時ファイル(zipファイル)の削除
	unlink($zipPath);
	exit();
	
	}else{
	header("Location:index.html");
	}
?>	

解説

$pdf= $_POST['pdf'];
$pathAry = array();
	for($i=0; $i&lt;sizeof($pdf); $i++){
     $pathAry[] = $pdf[$i];
    }

上記のようにチェックボックスを配列にしてファイル群の情報を取得します。
仮にpdf1.pdfとpdf2.pdfを取得したとする場合、下記のように並んでいることになります。

$pathAry = array();
	$pathAry[] = "pdf/pdf1.pdf";
	$pathAry[] = "pdf/pdf2.pdf";

出力されるzipファイルの名前は「$zipName」で設定しております。
複数回ダウンロードしてもファイル名がかぶらないように、file_プラスダウンロード時の年月日時が入るようにしております。
階層図にもあった「tmp」フォルダーは、zip作成時の一時フォルダーとして用意しております。
チェックボックスが未選択の場合は、何も処理せず、index.htmlに戻ります。
チェックが選択されている場合のみ、ファイルのダウンロードが可能になるしくみです。