36
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PSR7のHttp/Messageを使ったファイルアップロード処理

Last updated at Posted at 2015-07-01

とうとう策定されたPSR-7(Http/Message)を使った場合、ファイルアップロードの処理がどうなるか書いてみました。 

PSR-7の策定にまで持っていった「Matthew Weier O'Phinney」さんという方が作ったPSR-7実装「zendframework/zend-diactoros」を参考にしてます。他の実装では構築方法などが微妙に違うかもしれませんが、APIは同じになります。

サンプルコード

アップロードフォーム

次のようなアップロードフォームを想定します。

<form method="post" enctype="multipart/form-data">
  <input type="file" name="up[0]" />
  <input type="submit" />
</form>

名前が配列になってます。従来のPHPだと、この場合の処理がメチャクチャ面倒でした。

サーバー側の処理

まずはリクエストオブジェクトを生成します。

use Psr\Http\Message\UploadedFileInterface;
use Zend\Diactoros\ServerRequestFactory;

$request = ServerRequestFactory::fromGlobals();
if ($request->getMethod()!=='POST') {
    exit;
}
// UploadedFileInterfaceの配列を読み込む
$uploaded_files = $request->getUploadedFiles();
if (!isset($uploaded_files['up'][0]) || !$uploaded_files['up'][0] instanceof UploadedFileInterface) {
    exit;
}
/** @var UploadedFileInterface $upload */
$upload = $uploaded_files['up'][0];

一応、メソッドがPOSTであること、目的のファイルがアップロードされたことぐらいはチェックしてみました。

これで、アップロードされたフィアルについてのUploadedFileInterfaceのオブジェクトが取得出来ました。ここからは、この$uploadオブジェクトを操作します。

UploadedFileInterfaceオブジェクト

エラーチェック

ファイルのアップロードエラーをチェックします。例えば…

if ($upload->getError()===UPLOAD_ERR_NO_FILE) {
    die('ファイルをアップロードして下さい');
}
if ($upload->getError()===UPLOAD_ERR_FORM_SIZE) {
    die('サイズが大きすぎます');
}
if ($upload->getError()!==UPLOAD_ERR_OK) {
    die('OKじゃないです。エラーです');
}
// エラー無し

エラーチェックも簡単、というか迷わない感じです。

ファイルの操作

ストリームを取得して、中身を読み取ります。

$stream = $upload->getStream();
// streamを使って書きだす。
$stream->rewind();
while (! $stream->eof()) {
    echo $stream->read(4096);
}
// ファイルポインターを抜き出して、書きだす。
$fp = $stream->detach();
rewind($fp);
fpassthru($fp);

あるいは別ファイルへ移動します。

$upload->moveTo('/path/to/new/file');

アップロードエラーがある状態で、getStreamあるいはmoveToを使うと例外を投げます。またmoveToは一度しか使えません。もちろん移動する際にはmove_uploaded_fileを使ってアップロードされたファイルしか移動しません。

最後に

説明しなくても使えぐらい簡単なAPIと思いますが、PSR-7で便利になった点の一つだと思ったので書いてみました。

36
30
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?