50
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PHP 画像のアップロード

Last updated at Posted at 2020-01-03

#画像をアップロードし表示させる
【大まかな流れ】
◆フォームから画像を選択
◆画像ファイルかのチェック
◆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つの情報が格納されている

50
56
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?