PHPでファイルをアップロードするサンプル
PHPでファイルをアップロードするサンプルコードはそのへんにごろごろ転がっていますが、備忘録として。
PHPのファイルアップロード処理
簡単なのでサンプルをいきなりドン!
<html lang="ja">
<head>
<meta charset="utf-8">
</head>
<body>
<h1>アップロード処理のサンプル</h1>
<form enctype="multipart/form-data" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="1000000">
<input name="file" type="file">
<input type="submit" name="_upload" value="アップロード">
</form>
<?php
//[アップロード]ボタンの押下確認
if (isset($_POST['_upload'])) {
//ファイルをテンポラリから保存場所へ移動(但し本来は渡されたファイル名をそのまま使うのは危険)
$filename = './'.$_FILES['file']['name'];
if (move_uploaded_file($_FILES['file']['tmp_name'], $filename)) {
echo $_FILES['file']['name'].'をアップロードしました';
} else {
//エラー処理
}
}
?>
</body>
</html>
解説
- formタグに enctype="multipart/form-data" を付ける。
これを付けないと application/x-www-form-urlencodedが指定されたことになるため、添付ファイルが送れません。 - methodはPOSTで送る。
GETだとブラウザごとに最大長が異なり、IEだと2038文字、Chromeだと32464文字くらいの制限があります。まぁChromeで32464文字送れても、Webサーバー側が例えばApache2.2だとデフォルトでは8190文字が最大なのでその制限にひっかかるかも。いずれにせよ、ファイル送信のときはPOSTを使うべきでしょう。 - inputタグでアップロードできるファイルの最大サイズを指定(MAX_FILE_SIZE)
この最大サイズの確認はブラウザ任せなので、ブラウザを介しないPOSTがされた場合や、そもそもブラウザに何らかの不具合があった場合には無視される可能性もあるため、PHP側でもファイルサイズの確認などはするべきですが、それでもやはりフォーム側でもMAX_FILE_SIZEの指定はしておくべきです。(余計なトラフィックを発生させないためにも) - move_uploaded_fileでテンポラリからファイルを移動
ここでファイルの移動先に新しい名前を付けるため、サンプルではユーザーから渡されたファイル名をそのまま使っていますが、それは危険です。既にアップロードされているファイル名とかぶる可能性もありますし、悪意のあるファイル、例えば拡張子がphpのファイルをアップロードされてしまう可能性もあります。連番+拡張子など、サーバー側で作ったファイル名で保存すべきです。
この例だと[ファイルの選択]ボタンでファイルを選択せずとも[アップロード]ボタンを押下するとPOSTが発生してしまうので、実際にはJavaScriptでファイルが選択されたかどうかチェックする処理を入れたほうが良いでしょう。
また、サンプルなので便宜上、PHPスクリプトと同じディレクトリ('./')に保存していますが、アップロードされたファイルを公開ディレクトリにそのまま保存するのはおすすめできません。実行ファイルとかスクリプトとかをアップロードされてしまう可能性があるからです。仮に拡張子のチェックをしたとしても中身はベツモノのファイルを送られる可能性もあるので、やはり公開ディレクトリとは別の場所に保存して、ダウンロード等をするのはPHPのreadfile関数などを通したほうが良いでしょう。
JavaScriptでフォームの確認をする例
PHPのサンプルだけで済ませようと思いましたが、一応ファイルが選択されたかどうかチェックするサンプルくらいは載せておこうかな、と。
<h1>アップロード処理のサンプル</h1>
<form enctype="multipart/form-data" method="post" onsubmit="return checkForm();">
<input type="hidden" name="MAX_FILE_SIZE" value="1000000">
<input name="file" type="file">
<input type="submit" name="_upload" value="アップロード">
</form>
<script>
function checkForm()
{
if (document.getElementsByName('file')[0].value == '') {
alert('ファイルを選択してください');
return false;
}
return true;
}
</script>
解説
formタグのonsubmitイベント内で return false を返すとPOSTは実行されません。そのため、JavaScriptでcheckForm関数を作り、内容をチェックして正しくなければ false を返す、問題なければ trueを返す、という動作をしています。
まとめ
PHPでファイルをアップロードする極簡単なサンプルを紹介しました。
- formではenctype="multipart/form-data"を指定する
- PHPでは $_FILES という連想配列にファイル名等の情報が格納されている
- ファイルのアップロード確認には is_uploaded_file関数、移動には move_uploaded_file関数を使う
- 保存するファイル名はサーバー側で決めよう
といったところでしょうか。
複数ファイルのアップロードや、拡張子のチェックなどについても書こうと思いましたが、長くなったので、ひとまずこのへんで。