51
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Organization

PHP 画像のアップロード

画像をアップロードし表示させる

【大まかな流れ】
◆フォームから画像を選択
◆画像ファイルかのチェック
◆DBではなくサーバーのimageディレクトリに画像を保存
◆DBにはファイル名保存
◆DBのファイル名を元に画像表示

ファイル構造

test
 |-images (画像ファイル保存ディレクトリ)
 |-image.php(画像表示ファイル)
 |-upload.php(画像アップロード処理)

画像ファイル送信フォーム

upload.php
<h1>画像アップロード</h1>
<!--送信ボタンが押された場合-->
<?php if (isset($_POST['upload'])): ?>
    <p><?php echo $message; ?></p>
<?php else: ?>
    <form method="post" enctype="multipart/form-data">
        <p>アップロード画像</p>
        <input type="file" name="image">
        <button><input type="submit" name="upload" value="送信"></button>
    </form>
<?php endif;?>

送信ボタンが押された場合の処理を記載
・アップロードされたファイルが画像ファイルではなかった場合はエラーメッセージ
・inputタグでfileを指定

upload.php
<?php
$dsn = "mysql:host=localhost; dbname=xxx; charset=utf8";
$username = "xxx";
$password = "xxx";
try {
    $dbh = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
    echo $e->getMessage();
}
    if (isset($_POST['upload'])) {//送信ボタンが押された場合
        $image = uniqid(mt_rand(), true);//ファイル名をユニーク化
        $image .= '.' . substr(strrchr($_FILES['image']['name'], '.'), 1);//アップロードされたファイルの拡張子を取得
        $file = "images/$image";
        $sql = "INSERT INTO images(name) VALUES (:image)";
        $stmt = $dbh->prepare($sql);
        $stmt->bindValue(':image', $image, PDO::PARAM_STR);
        if (!empty($_FILES['image']['name'])) {//ファイルが選択されていれば$imageにファイル名を代入
            move_uploaded_file($_FILES['image']['tmp_name'], './images/' . $image);//imagesディレクトリにファイル保存
            if (exif_imagetype($file)) {//画像ファイルかのチェック
                $message = '画像をアップロードしました';
                $stmt->execute();
            } else {
                $message = '画像ファイルではありません';
            }
        }
    }
?>

<h1>画像アップロード</h1>
<!--送信ボタンが押された場合-->
<?php if (isset($_POST['upload'])): ?>
    <p><?php echo $message; ?></p>
    <p><a href="image.php">画像表示へ</a></p>
<?php else: ?>
    <form method="post" enctype="multipart/form-data">
        <p>アップロード画像</p>
        <input type="file" name="image">
        <button><input type="submit" name="upload" value="送信"></button>
    </form>
<?php endif;?>

【保存している画像名について】
ユーザーが上げた画像名が使われてしまう形になっていると下記の問題が発生する。
・悪意のあるユーザーに、サーバーに不具合が発生するような名前を設定される恐れがある
・長い名前を設定されていると保存できない
・保存できないファイル名がある(?.jpgなど)
$image = uniqid(mt_rand(), true);
画像ファイル名をサーバー側でユニーク化して保存

【画像アップロードについて】
画像ファイルかの確認を行わないと画像ファイル以外をアップロードした際も保存が完了され、空の画像が表示される
$image .= '.' . substr(strrchr($_FILES['image']['name'], '.'), 1);で拡張子を取得
exif_imagetype関数で画像ファイルかの確認
参考:exif_imagetype

【画像の保存方法について】
データベースに画像を保存してしまうと、ユーザーデータを取得する時に画像データが大きい為、データ取得の時間が長くなってしまう恐れがある。
move_uploaded_file($_FILES['image']['tmp_name'], './images/' . $image); でディレクトリに画像を保存
そのため下記手順で表示させる
1. サーバー内に画像を保存する為のディレクトリを作成(images)
2. 1のディレクトリに画像を保存、画像のファイル名をデータベースに保存(ユニーク化されたもの)
3. データベースの画像のファイル名を元に画像を表示させる

画像表示

image.php
<?php
$dsn = "mysql:host=localhost; dbname=xxx; charset=utf8";
$username = "xxx";
$password = "xxx";
$id = rand(1, 5);
try {
    $dbh = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
    echo $e->getMessage();
}
    $sql = "SELECT * FROM images WHERE id = :id";
    $stmt = $dbh->prepare($sql);
    $stmt->bindValue(':id', $id);
    $stmt->execute();
    $image = $stmt->fetch();
?>

<h1>画像表示</h1>
<img src="images/<?php echo $image['name']; ?>" width="300" height="300">
<a href="upload.php">画像アップロード</a>

参考

アップロードファイルの情報を取得する:$_FILES
スーパーグローバル変数の$_FILESは5つの情報が格納されている

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
51
Help us understand the problem. What are the problem?