入力フォーム画面でのファイルのアップロードは、他のテキストの入力と違っていろいろなことを考慮する必要があり、開発はそう簡単ではありません。PHPのマニュアルでも、説明のためだけに一章を費やしています。

もちろん、Laravelを使うことで開発はかなり簡単になるのだけれど、注意する点やアップしたファイルをどう使用するか...などたくさんのトピックあります。以下、いくつか興味あるトピックをリストしました。

  • ファイルのサイズの制限:制限なしでも制限ある
  • ファイルのMIMEタイプの制限:画像ファイルだけをアップ
  • ファイルのアップの進行状況表示 :いつファイルのアップが終わるのかな
  • ファイルのウィルスの検出:そんなこと可能かな
  • アップしたファイルをメールで送信:届かないのはどうして
  • アップしたファイルをダウンロード:MIMEからファイルの拡張子を作成
  • アップしたファイルを配信:Amazonのウェブサービスを使用する

ファイルのサイズの制限:制限なしでも制限ある

まず、ファイルアップロードのフォームをプログラムしましょう。

<form
    method="POST"
    action="/demo/public/user/upload"
    class="form-horizontal"
    role="form"
    enctype="multipart/form-data">
    {{ csrf_field() }}

		<div class="form-group{{ $errors->has('file') ? ' has-error' : '' }}">
			<label class="col-md-4 control-label">File</label>

			<div class="col-md-6">
				<input type="file" name="file">
				@if ($errors->has('file'))
					<span class="help-block">
						<strong>{{ $errors->first('file') }}</strong>
					</span>
				@endif
			</div>
		</div>
		<div class="form-group">
			<div class="col-md-6 col-md-offset-4">
                    <input class="btn btn-primary" type="submit" value="Upload">
			</div>
		</div>
</form>

このフォームのコントローラで、アップするファイルの制限を課します。

namespace App\Http\Controllers\User;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\User;

use Auth;
use Validator;

class UserController extends Controller
{
 ...
 
    public function getUpload()
    {
        return view('user/upload');
    }

    public function postUpload(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'file' => 'required|max:10240'
        ]);

        if ($validator->fails())
        {
            return back()->withInput()->withErrors($validator);
        }

        return redirect('user/upload');

    }
}

'file' => 'required|max:10240'ここ大事です。maxで指定する最大のファイルのサイズの単位は、バイトではなくキロバイト(KByte)です。つまり、10240は。10メガバイト(10M)となります。

さて、これでファイルをアップロードしてみましょう。8MBのファイルをアップしてみます。しかし、送信ボタンを押した後、TokenMismatchExceptionのエラーとなってしまいます。

どうしてアップできないのでしょう?

制限しているのはプログラムだけではなく、サーバーのPHPの設定でも制限があるからなのです。Unix系のサーバーなら、/etc/php.iniにおいて以下の2か所を編集する必要あります。8M20Mとでも設定しましょう。

...
post_max_size = 8M
upload_max_filesize = 8M
...

これで、ウェブサーバーを再スタートしてみてください。

1つ残る疑問は、どうしてエラーがPHPの制限のエラーでなくTokenMismatchExceptionのエラーなのでしょう。これは、制限を超えることにより、送信した入力の値が空となり、Laravelが期待するCSRF(クロスサイトリクエストフォージェリ)のトークンの値が入って来なかったからです。

By khino