REDLINE MAGAZINE | PHP ファイルのアップロード 勉強メモREDLINE MAGAZINEトップページへ

すべてのエントリを見る

PHP ファイルのアップロード 勉強メモ

フォーム側のお約束事はこれだけ

  • form要素に「enctype="multipart/form-data"」を追加する。
  • inputのtype属性には「file」を指定。
  • 必ずPOSTメソッドを指定。

アップロード処理の流れ

  1. フォームに入力→送信
  2. テンポラリファイルとしてアップロードされる
  3. ディレクトリにコピーして保存

テンポラリファイルとしてアップロードされたままにしておくと処理完了と同時に削除されてしまうので、ファイルを保存するために書き込み権限のあるディレクトリにコピーする。

$_FILES

アップロードされたデータの内容は「$_FILES」に入る。

$_FILES['userfile']['name']
クライアントマシンの元のファイル名。
$_FILES['userfile']['type']
ファイルの MIME 型。ただし、ブラウザがこの情報を提供する場合。 例えば、"image/gif" のようになります。 この MIME 型は PHP 側ではチェックされません。そのため、 この値は信用できません。
$_FILES['userfile']['size']
アップロードされたファイルのバイト単位のサイズ。
$_FILES['userfile']['tmp_name']
アップロードされたファイルがサーバー上で保存されているテンポラリファイルの名前。
$_FILES['userfile']['error']
エラーコード(PHP: エラーメッセージの説明 - Manual

ということで、アップロードしたファイルをサーバー上で保存する時は、$_FILES['userfile']['tmp_name']を適当な場所にコピーすればいいってことですね。

手順

  1. ファイルを保存するディリクトリを決める(どっかのディレクトリに入れたい場合は)
  2. アップされたテンポラリファイルファイル名を取得
  3. move_uploaded_file関数を使って、1で決めたディレクトリへコピー

move_uploaded_file アップロードされたファイルを新しい位置に移動する

「move_uploaded_file (アップロードしたファイル名,ファイルのコピー先)」という書き方。

簡単なサンプル

<form action="<?= $_SERVER["PHP_SELF"]; ?>" method="post" enctype="multipart/form-data">
<p><input type="file" name="data" /> <input type="submit" value="アップロード"></p>
</form>
<?php
$updir = "./data";
$tmp_file = @$_FILES['data']['tmp_name'];
$copy_file = @$_FILES['data']['name'];
move_uploaded_file($tmp_file,"$updir/$copy_file");
?>

ファイル名を変更して保存する場合 その1

ファイル名が重複しないようにするにはどうしたらいいんかなって考えたとき日付と時間にしちゃえばいいじゃんっていう安易な発想からアップした日時をファイルの名にしたサンプル。

<?php
$updir = "./data";
$tmp_file = @$_FILES['data']['tmp_name'];
@list($file_name,$file_type) = explode(".",@$_FILES['data']['name']);
$copy_file = date("Ymd-His") . "." . $file_type;
move_uploaded_file($tmp_file,"$updir/$copy_file");
?>

リネームするファイル名の拡張子の部分、typeを取得してswitch振り分けとかいろいろ迷ったけど一番短く書けそうなのを採用。元のファイル名を「.」で分割して最後の部分をゲットする方法にしてみた。もっといいやり方があるんかもしれないけど・・・。

ファイル名を変更して保存する場合 その2

連番をつけるサンプル。ファイルを保存するディレクトリ内のファイル数を取得して1ずつ増やすっていうやり方にしたいと思ったんだけど、マニュアルを探しまくってもそれを一発でなんとかする関数が見つけられなかったので2段階方式でやってみた。この関数使ってみる。

scandir(PHP5) 指定されたパスのファイルとディレクトリのリストを取得する

scandirで返ってくる値は配列になってるので、その数をcountで取得したい。で、なんかこれで取得すると見知らぬものがもれなくついてくる。「.」と「..」この人達は何だろう。どっかで読んだ事ある気がするけど思い出せない・・・カレントと上のディレクトリの事かな。まぁいいや。

とりあえず数が欲しいだけなので無視して、それらを含めて取得した数から1引いたものを使う事にした。気持ち的には2引いた数にするのがスッキリだけど、2引くと最初の番号が0になっちゃう。なんとなく1から始めたかったので1引いた数にしてみた。「data-番号.拡張子」の形で保存してみる。

<?php
$updir = "./data";
$array_file = scandir($updir);
$count_file = count($array_file) -1;
$tmp_file = @$_FILES['data']['tmp_name'];
@list($file_name,$file_type) = explode(".",@$_FILES['data']['name']);
$copy_file = "data-" . $count_file . "." .$file_type;
move_uploaded_file($tmp_file,"$updir/$copy_file");
?>

もちろんそのディリクトリの中に他のファイルやディレクトリがあったらアップロードしたファイルに対しての連番が飛んだりするんかもしれんけど、まぁ重複はしないってことで・・・。

ファイル名を変更して保存する場合 その3

連番の形をもうちょい整えるサンプル。整えるっていうか、上のサンプルだと桁が上がると「1.11.12・・・2.3.4.5.6.7.8.9」みたいな並び方になるのが私はあまり好きじゃないので番号をsprintf関数で5桁にした。「data-00001.拡張子」みたいな形にする。

<?php
$updir = "./data";
$array_file = scandir($updir);
$count_file = count($array_file) -1;
$count_file = sprintf('%05d',$count_file); 
$tmp_file = @$_FILES['data']['tmp_name'];
@list($file_name,$file_type) = explode(".",@$_FILES['data']['name']);
$copy_file = "data-" . $count_file . "." .$file_type;
move_uploaded_file($tmp_file,"$updir/$copy_file");
?>

php.iniの設定

ファイルのアップロードに関連するphp.iniの設定はこの辺り。うまくアップできない時は設定を確認。file_uploadsupload_max_filesizeupload_tmp_dirpost_max_sizemax_input_time

<< dat から1行ずつ抜き出して xml 書き出し | PHP ランダム表示機能付きバナーリンク集 >>

トラックバック

このエントリーのトラックバックURL:
http://redline.hippy.jp/cgi/mt/mt-tb.cgi/239

コメント (4)

PHPコード内での@によるエラー抑制はパフォーマンス的によくないですよ。

またエラーメッセージ拾えないと困る場合もあるだろうし。

>atsushiさん
コメントありがとうございますー!
そういえば、それ以前もアドバイス頂いたんでした・・・><
$tmp_file = @$_FILES['data']['tmp_name'];
こういうのを
$tmp_file = isset($_FILES['data']['tmp_name']) ? $_FILES['data']['tmp_name'] : NULL;
こうしたらいいんですよね。
勉強になります。ありがとうございます(n'∀')η

$tmp_fileとするより$_FILES['userfile']['tmp_name']の方が解りやすかったりしますよ。
時と場合によりますけど。

>resさん
コメントありがとうございましたー。
いつもいつも一旦変数に入れないほうがいい場合ってのも考えた方がいいんですね。勉強になりますー。ありがとうございました。




※コメント欄に「<」「>」等を含むソースを記載する場合は実体参照に変換してください。

このページの一番上へ

その他の情報など

最近のコメント

PHP オブジェクト指向の勉強
  • Red - 2010.01.08
  • hogepage - 2010.01.21
  • Red - 2010.01.22
  • - 2011.11.27
  • houseiii - 2011.11.27
Fireworks トリミング画像を一括書出 CS4編
  • Iper - 2009.06.27
  • Red - 2009.06.27
  • mala - 2011.11.17
  • Red - 2011.11.18
jQueryでボックスを上下左右中央に簡単配置
overflow を使用したボックス背景のこと
  • - 2007.12.13
  • Red - 2007.12.13
  • - 2007.12.13
  • Red - 2007.12.13
  • hj - 2011.09.23
IE6 → 透過PNG+overflow=混ぜるな危険(追記有)

メッセージを送る

こちらのメッセージ送信フォームは閉鎖させて頂きました。
御用の方は新しい方のブログ にコメント頂くか、 連絡用のフォーム もありますので、そちらからご連絡ください。