1.新しいlesson5というフォルダをドキュメントルート(htdocs)以下に作成する。
2.lesson5フォルダの中にuploadsというフォルダを作成する。パーミッションはユーザ、グループ、その他に対して読み書きの権限をあたえる。(666)

画像アップロード

3.lesson5の直下に以下のようにform.phpを作成する。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>PHPLesson</title>
</head>
<body>
   <p>ファイルアップロード</p>
   <form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="upfile">
    <button type="submit">送信</button>
   </form>
</body>
</html>

4.lesson5の直下にupload.phpを以下のように作成する。

<?php
$info=pathinfo($_FILES['upfile']['name']);
/*
print_r($_FILES['upfile']);
print_r($info);
exit;
*/
$ext=['gif','jpg','jpeg','png'];//許す拡張子のリスト
$result=$_FILES['upfile']['error'];//エラーはあるか(0:UPLOAD_ERR_OKなら正常)
if($result !==UPLOAD_ERR_OK){
  //アップロードはエラーはないか?
  $error ='アップロードエラーが発生しました。';
}else if(!in_array(strtolower($info['extension']),$ext)){
//拡張子は許されたものか?
  $error='画像以外のファイルはアップロードできません。';
}elseif(!move_uploaded_file($_FILES['upfile']['tmp_name'],'uploads/'.time().'.'.$info['extension'])){
  //書き込みに成功したか?
  $error='書き込みに失敗しました。';
}
//エラーがあったら出力して終了
if(isset($error)){
  die('error:'.$error);
}
//アップロードに成功したらformにリダイレクト
/*
print_r($_SERVER);
exit;
*/
header('location:http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/form.php');

5.実行してみよう。画像をアップロードしてuploadsフォルダに画像が格納されれば成功だ。

6.同様に2〜3枚アップロードしてみよう。

ディレクトリの内容を表示

7.list.phpを以下のように作成する。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>PHPLesson</title>
</head>
<body>
  <p>ファイルリスト</p>
  <table border="1">
    <tr><th>画像</th><th>ファイル</th><th>サイズ</th></tr>
    <?php
    const DOC_ROOT='./uploads/';
    clearstatcache();//キャッシュクリア
    //ディレクトリの取得(ディレクトリのオープンに失敗したら終了(@はエラーを出力しないようにする))
    $dir=@opendir(DOC_ROOT) or die('フォルダが開けませんでした。');
    //ディレクトリの走査
    while($file=readdir($dir)){
      //ファイルか?(.や..やディレクトリが除外される)
      if(is_file(DOC_ROOT.$file)){
        $path=DOC_ROOT.$file;
        ?>
        <tr>
          <td><img src="<?=$path?>" width="100"></td>
          <td><?=$file?></a></td></td>
          <td><?=round(filesize($path)/1024)?>kb</td>
        </tr>
        <?php
      }
    }
    closedir($dir);
    ?>
  </table>
</body>
</html>


8.実行してみよう。uploadsフォルダに入っている画像がすべて表示されれば成功だ。

ダウンロード機能の実装

9.先ほどのlist.phpの24行目を以下のように修正する。

<td><a href="download.php?file=<?=$file?>"><?=$file?></a></td></td>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>PHPLesson</title>
</head>
<body>
  <p>ファイルリスト</p>
  <table border="1">
    <tr><th>画像</th><th>ファイル</th><th>サイズ</th></tr>
    <?php
    const DOC_ROOT='./uploads/';
    clearstatcache();//キャッシュクリア
    //ディレクトリの取得(ディレクトリのオープンに失敗したら終了(@はエラーを出力しないようにする))
    $dir=@opendir(DOC_ROOT) or die('フォルダが開けませんでした。');
    //ディレクトリの走査
    while($file=readdir($dir)){
      //ファイルか?(.や..やディレクトリが除外される)
      if(is_file(DOC_ROOT.$file)){
        $path=DOC_ROOT.$file;
        ?>
        <tr>
          <td><img src="<?=$path?>" width="100"></td>
          <td><a href="download.php?file=<?=$file?>"><?=$file?></a></td></td>
          <td><?=round(filesize($path)/1024)?>kb</td>
        </tr>
        <?php
      }
    }
    closedir($dir);
    ?>
  </table>
</body>
</html>

10.download.phpを以下のように作成する。

<?php
const DOC_ROOT='./uploads/';
$isContain=false;//ホワイトリストに含まれているか?
/*
ホワイトリストとなるディレクトリを指定
(このディレクトリ以外のファイルはダウンロードさせない)
*/
$dir=opendir(DOC_ROOT);
//ディレクトリの走査
while($file=readdir($dir)){
  if(is_file(DOC_ROOT.$file)){
    $path=DOC_ROOT.$file;//対象となったパスを保存しておく
    //クエリで指定されたファイルがディレクトリにあればOK
    if($_GET['file']===$file){
      //あったのでフラグをtrue
      $isContain=true;
      //抜ける
      break;
    }
  }
}
closedir($dir);//dirを閉じる
//クエリで渡されたファイル名が不正だったら終了
if(!$isContain){
  die('不正なパスが指定されました。');
}
//不正でなければダウンロードする
$filesize = filesize($path);
header('Content-Type:application/octet-stream');
header('Content-Length:'.$filesize);
header('Content-Disposition:attachment;filename='.$file);
readfile($path);

11.list.phpのリンクをクリックして画像がダウンロードされれば成功だ。

ファイル削除の実装

12.list.phpを以下のように修正する。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>PHPLesson</title>
</head>
<body>
  <p>ファイルリスト</p>
  <a href="form.php">画像を登録</a>
  <table border="1">
<!--変更あり-->
    <tr><th>画像</th><th>ファイル</th><th>サイズ</th><th></th></tr>
    <?php
    const DOC_ROOT='./uploads/';
    clearstatcache();//キャッシュクリア
    //ディレクトリの取得(ディレクトリのオープンに失敗したら終了(@はエラーを出力しないようにする))
    $dir=@opendir(DOC_ROOT) or die('フォルダが開けませんでした。');
    //ディレクトリの走査
    while($file=readdir($dir)){
      //ファイルか?(.や..やディレクトリが除外される)
      if(is_file(DOC_ROOT.$file)){
        $path=DOC_ROOT.$file;
        ?>
        <tr>
          <td><img src="<?=$path?>" width="100"></td>
          <td><a href="download.php?file=<?=$file?>"><?=$file?></a></td></td>
          <td><?=round(filesize($path)/1024)?>kb</td>
<!--変更あり-->
          <td><a href="unlink.php?file=<?=$file?>" onclick="return confirm('削除してよろしいですか?')">削除</a></td></td>
        </tr>
        <?php
      }
    }
    closedir($dir);
    ?>
  </table>
</body>
</html>

13.unlink.phpを以下のように作成

<?php
const DOC_ROOT='./uploads/';
$isContain=false;//ホワイトリストに含まれているか?
/*
ホワイトリストとなるディレクトリを指定
(このディレクトリ以外のファイルはダウンロードさせない)
*/
$dir=opendir(DOC_ROOT);
//ディレクトリの走査
while($file=readdir($dir)){
  if(is_file(DOC_ROOT.$file)){
    $path=DOC_ROOT.$file;//対象となったパスを保存しておく
    //クエリで指定されたファイルがディレクトリにあればOK
    if($_GET['file']===$file){
      //あったのでフラグをtrue
      $isContain=true;
      //抜ける
      break;
    }
  }
}
closedir($dir);//dirを閉じる
//クエリで渡されたファイル名が不正だったら終了
if(!$isContain){
  die('不正なパスが指定されました。');
}
//ファイルを削除
unlink($path);
//listにリダイレクト
header('location:http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/list.php');

14.upload.phpの最後の行を以下のように修正する。

header('location:http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/list.php');

15.以上で終了だ。Webアプリケーションにおいて画像の扱いは必須になってきている。基本的な扱い方法を理解しておこう。