フォームで選択した画像などのファイルをピュアPHPでアップロードする方法

ピュアPHPって言葉ありますか?笑

ようはフレームワークを使わない純粋なPHPでファイルアップロードをしてみようって話です。

対象はPHP初心者に毛が生えたような人か、僕のように経験を積んでも覚えの悪い人です。

 

ちなみにフレームワークを使うと、そのフレームワークの書き方があったりしますので今回の内容はコピペで使えないです。

しかし、ファイルアップロードがどうなっているか分かればPHPに限らず他の言語でもイメージはしやすいはずです。

目次

画像を選択するフォームを用意する

まずはアップロードする画像を選択するために、HTMLに画像選択の項目を用意します。

フォームを作るときは、ファイルタイプのinputタグだけでなく、formタグにも仕掛けが必要です。

フォームのサンプル

<form action="form.php" method="POST" enctype="multipart/form-data">
	<p>名前</p>
	<input type="text" name="yourname"">
	<p>ファイルを選択</p>
	<input type="file" name="yourfile"">
	<input type="submit" value="送信">
</form>

名前は今回は要らないですが、元々あった項目ということで、それもちゃんと動くか検証のために入れておきました。

ポイントは、<input type=”file” です。

ファイルを選択する場合はinputタグの file を使います。

これで以下のような項目が作れます。

そして、ファイル選択項目に入力した情報をサーバーに送信するために、formタグに enctype=”multipart/form-data” を追加します。

enctype=”multipart/form-data” は、ファイル自体をサーバーに送るためのおまじない的なものです。(それ以上知りません)

 

inputタグに入力されたデータは、PHP側の$_POSTで受け取ります。

だけどファイルの場合は$_FILESで受け取るようになります。

言葉で説明しても難しいので実際に enctype=”multipart/form-data” ありと無しで結果を出力してみましょう。

enctype=”multipart/form-data” なしのパターン

<form action="form.php" method="POST">

の状態です。

以下のようなコードを作ってみました。

<html>
	<head>
		<meta charset="UTF-8">
		<title>PHPテスト</title>
		<meta name="description" content="このページの概要を書く">
		<link rel="stylesheet" href="css/style.css">
	</head>
	<body>
		<pre>
		<?php
		echo "POST<br />";
		var_dump($_POST);
		echo "FILES<br />";
		var_dump($_FILES);
		?>
		</pre>

		<form action="form.php" method="POST">
			<p>名前</p>
			<input type="text" name="yourname"">
			<p>ファイルを選択</p>
			<input type="file" name="yourfile"">
			<input type="submit" value="送信">
		</form>
	</body>
</html>

名前に「ああ」、ファイルは「neko.jpg」を選択します。

実行結果は次のようになりました。

POST
array(2) {
  ["yourname"]=>
  string(6) "ああ"
  ["yourfile"]=>
  string(8) "neko.jpg"
}
FILES
array(0) {
}

通常通り、POSTデータの中に入力値が入っています。

では、enctype=”multipart/form-data” ありだとどうでしょう?

enctype=”multipart/form-data” ありのパターン

フォームタグを、

<form action="form.php" method="POST" enctype="multipart/form-data">

にしただけです。

他のコードは上で紹介したものと同じです。

実行結果は次のようになりました。

POST
array(1) {
  ["yourname"]=>
  string(6) "ああ"
}
FILES
array(1) {
  ["yourfile"]=>
  array(5) {
    ["name"]=>
    string(8) "neko.jpg"
    ["type"]=>
    string(10) "image/jpeg"
    ["tmp_name"]=>
    string(25) "C:\xampps\tmp\php3413.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(1335868)
  }
}

ファイル名だけでなく、ファイルの種類やサイズなども取得できています。

tmp_name の “C:\xampps\tmp\php3413.tmp” は、サーバーが一時フォルダに画像をアップロードしたんですね。

サーバー側でファイルをアップロードするピュアPHP

上の作ったフォームで送信した場合どんなデータがどんな形式で受け取れるかだいたい分かったと思います。

次は実際にアップロード処理をPHPで書いていきます。

 

とは言っても、上のHTMLのフォームまでで実際にファイルはアップロードされています。

PHPで行うことは、サーバーの一時フォルダにアップロードされたファイルを、任意の場所に移動することです。

その関数が move_uploaded_file() になります。

[aside type=”normal”]move_uploaded_file($一時ファイル, $移動先)[/aside]

$一時ファイルは、$_FILESの tmp_name のことです。

$移動先は、一時フォルダにアップロードされたファイルの移動先です。

一時フォルダ内のデータは削除されてしまいます。

移動先ですが、ファイル名も指定します。ここで指定したファイル名が実際に保存されるファイルの名前になります。

 

では実際に動かしてみましょう。

<?php
$msg = "";
if (is_uploaded_file($_FILES["yourfile"]["tmp_name"])) {
	if (move_uploaded_file($_FILES["yourfile"]["tmp_name"], "images/" . $_FILES["yourfile"]["name"])) {
		$msg = $_FILES["yourfile"]["name"] . "をアップロードしました。";
	} else {
		$msg = "ファイルをアップロードできません。";
	}
} else {
	$msg = "ファイルが選択されていません。";
}
?>

is_uploaded_file() はアップロードされたファイルが正しいかをチェックします。

アップロードファイルを選択しなかったら false になります。

 

アップロード先のフォルダは、実行しているPHPファイルと同じ階層に images フォルダを作成し、その中にアップすることにしました。

images フォルダが無いとエラーになります。

 

実際にアップロードが完了すると、images フォルダに選択した画像がアップロードされます。

拡張子のチェック

上のコードではファイルがアップロード出来たかどうかのチェックはしていますが、何のファイルをアップしているかはチェックしていません。

PHPファイルとかアップロードされて実行されたらセキュリティ完全に無い状態です。

そこで拡張子が何かをチェックして画像ファイル(jpgとpng)だけアップロードできるようにしました。

 

拡張子のチェックは以下の手順で行います。

  • $_FILES[“yourfile”][“name”] で取得したファイル名から拡張子を取得する。
  • 拡張子の取得は pathinfo() を使い、第2引数に PATHINFO_EXTENSION を指定することで拡張子だけを取得できます。
  • あとは事前に定義した拡張子に含まれているかをチェックします。

 

上で作成したサンプルコードに拡張子チェックを入れたサンプルです。

<?php
$msg = "";
if (isset($_FILES["yourfile"])) {
	if (is_uploaded_file($_FILES["yourfile"]["tmp_name"])) {
		
		// ファイル名を取得
		$filename = $_FILES["yourfile"]["name"];
		// 拡張子を取得
		$ext = pathinfo($filename, PATHINFO_EXTENSION);
		
		// 拡張子をチェックする。
		$okexp = array('jpg', 'png');
		if (in_array($ext, $okexp)) {
			if (move_uploaded_file($_FILES["yourfile"]["tmp_name"], "images/" . $_FILES["yourfile"]["name"])) {
				$msg = $_FILES["yourfile"]["name"] . "をアップロードしました。";
			} else {
				$msg = "アップロードに失敗しました。";
			}
		} else {
			$msg = "この拡張子はアップロードできません。";
		}
	} else {
		$msg = "ファイルが選択されていません。";
	}
}
?>
<html>
	<head>
		<meta charset="UTF-8">
		<title>PHPテスト</title>
		<meta name="description" content="このページの概要を書く">
		<link rel="stylesheet" href="css/style.css">
	</head>
	<body>
		<p><?php echo $msg; ?></p>
		<form action="form.php" method="POST" enctype="multipart/form-data">
			<p>名前</p>
			<input type="text" name="yourname"">
			<p>ファイルを選択</p>
			<input type="file" name="yourfile"">
			<input type="submit" value="送信">
		</form>
	</body>
</html>

まとめ

ファイルのアップロードには、HTMLのinputタグのタイプが file を使う。

inputタグだけでなく、formタグにもファイルをアップロードするおまじない「enctype=”multipart/form-data”」を入れる。

PHP側は、一時フォルダにアップロードされたファイルを仕様通りの場所に移動する処理を書く。

ファイル種別のチェックは拡張子で行う。

この記事を書いた人

ライターのプロフィールが入ります。このライター情報を入れたくない場合は管理画面の ユーザー > あなたのプロフィールの「プロフィール情報」を未入力にすれば表示されません。逆に「プロフィール情報」を入力することでライター情報を表示できます。

コメント

コメントする

CAPTCHA


目次
閉じる