アップロードした画像をPHPで保存するメモ

June 11th, 2012

DEMO

画像ファイルのアップロードを試してみたので、その時のメモ。


注意

iPhone/iPad の場合は「input type=file」が対応してないので(正確にはSafariが、Opera Miniは対応している。)、別の方法を採るしかない。


追記:iOS 6から「input type=file」が対応されている。


enctype属性とMAX_FILE_SIZE

ファイルのアップロードをする場合は、formタグにenctype属性を指定しないと、ファイルデータが送信されない。

MAX_FILE_SIZEを指定しておくとサイズオーバーの時、早い段階で処理を中断してくれるので長時間の処理待ちを防ぐ事ができます。ただし、MAX_FILE_SIZEを指定してもPHP側の最大サイズが変わる事はありません。

<form action="/" method="post" id="upload" name="upload" enctype="multipart/form-data">
    <!-- 1024 = 1KB -->
    <input type="hidden" name="MAX_FILE_SIZE" value="1024" />
    <input type="file" name="upload_file" />
    <input type="submit" name="submit" value="Upload" />
</form>

送信されたデータを取得する

送信されたファイルデータは「$_FILES」に格納される。「$_POST」じゃないので注意。

<?php
$file = $_FILES['upload_file'];
$tmp_name = $file['tmp_name']; // 一時ファイルのパス
?>

ファイルデータを判別して画像リソースを取得する

<?php
$tmp_size = getimagesize($tmp_name); // 一時ファイルの情報を取得
$img = $extension = null;
switch ($tmp_size[2]) { // 画像の種類を判別
    case 1 : // GIF
        $img = imageCreateFromGIF($tmp_name);
        $extension = 'gif';
        break;
    case 2 : // JPEG
        $img = imageCreateFromJPEG($tmp_name);
        $extension = 'jpg';
        break;
    case 3 : // PNG
        $img = imageCreateFromPNG($tmp_name);
        $extension = 'png';
        break;
    default : break;
}
?>

保存時のファイル名を作成する

保存先に指定するディレクトリ(/upload)のパーミッションを「0744」または「0777」に変更しておく。

<?php
$save_dir = '/images/upload/';
$save_filename = date('YmdHis');
$save_basename = $save_filename. '.'. $extension;
$save_path = $_SERVER["DOCUMENT_ROOT"]. $save_dir. $save_basename;
while (file_exists($save_path)) { // 同名ファイルがあればファイル名を変更する
    $save_filename .= mt_rand(0, 9);
    $save_basename = $save_filename. '.'. $extension;
    $save_path = $_SERVER["DOCUMENT_ROOT"]. $save_dir. $save_basename;
}
?>

新しく画像データを作成する

アップロードされたファイルをそのまま保存したくないので、画像リソースを元に画像のサイズを変更したデータを作成します。

<?php
$img_size = getImageSize($img, 500); // 最大500pxの画像サイズ
$out = imageCreateTrueColor($img_size['w1'], $img_size['h1']); // 新しい画像データ

// 画像サイズを変更する関数
function getImageSize($img = null, $maxsize = 300) {
    if (!$img) return false;
    $w0 = $w1 = imageSx($img); // 画像リソースの幅
    $h0 = $h1 = imageSy($img); // 画像リソースの高さ
    if ($w0 > $maxsize) { // $maxsize以下の大きさに変更する
        $w1 = $maxsize;
        $h1 = (int) $h0 * ($maxsize / $w0);
    }
    if ($h1 > $maxsize) {
        $w1 = (int) $w1 * ($maxsize / $h1);
        $h1 = $maxsize;
    }

    return array(
        'w0'=>$w0, // 元画像の幅
        'h0'=>$h0, // 元画像の高さ
        'w1'=>$w1, // 保存画像の幅
        'h1'=>$h1, // 保存画像の高さ
    );
}
?>

新しい画像データにアップロードファイルの情報をコピーする

<?php
// 背景色を設定する
$color_white = imageColorAllocate($out, 255, 255, 255); // 色データを作成
imageFill($out, 0, 0, $color_white);

// $imgの画像情報を$outにコピーする
imageCopyResampled(
    $out, // コピー先
    $img, // コピー元
    0, 0, 0, 0, // 座標(コピー先:x, コピー先:y, コピー元:x, コピー元:y)
    $img_size['w1'], $img_size['h1'], $img_size['w0'], $img_size['h0'] // サイズ(コピー先:幅, コピー先:高さ, コピー元:幅, コピー元:高さ)
);
?>

新しい画像データを保存する

<?php
saveImage($out, $save_path, $extension);

// 画像を保存する関数
function saveImage($img = null, $file = null, $ext = null) {
    if (!$img || !$file || !$ext) return false;
    switch ($ext) {
        case "jpg" :
            $result = imageJPEG($img, $file);
            break;
        case "gif" :
            $result = imageGIF($img, $file);
            break;
        case "png" :
            $result = imagePNG($img, $file);
            break;
        default : return false; break;
    }
    chmod($file, 0644); // パーミッション変更
    return $result;
}
?>

DEMO

June 11th, 2012