Request

Learn how to work with uploaded files via the http request object

Uploaded File

Get The Uploaded Files

You may access uploaded files using the getUploadedFiles() method on the request object like so:

// get all uploaded files
$files = $request->getUploadedFiles();

This returns an array of \Psr\Http\Message\UploadedFileInterface keyed by the name of the <input /> element.

Handling Uploads

Let's suppose we have a very simple upload form like so:

<!-- make sure the attribute enctype is set to multipart/form-data -->
<form method="POST" action="/upload" enctype="multipart/form-data">
	<input type="file" name="uploaded_file" />
	<input type="submit" />
</form>

Since the form action attribute points to the '/upload' endpoint, we will have to write a route that handle's the upload route like so:

$app->post('/upload', function($request, $response, $next) {
    $files = $request->getUploadedFiles();

    $uploaded_file = $files['uploaded_file'];
});
Multiple Files Upload:

To upload multiple files, we will have to add the multiple attribute to our upload field along with appending [] to the name field like so:

<form method="POST" action="/upload" enctype="multipart/form-data">
	<input type="file" name="uploaded_files[]" multiple />
	<input type="submit" />
</form>

Alternatively, you could also create any number of distinct file upload fields with the same name followed by [] like so:

<input type="file" name="uploaded_files[]" />
<input type="file" name="uploaded_files[]" />
<!-- ... -->

Next, we can handle multiple uploaded files like so:

$app->post('/upload', function($request, $response, $next) {
    $files = $request->getUploadedFiles();

    // handle multiple inputs with the same key
    foreach ($files['uploaded_files'] as $uploadedFile) {
        if ($uploadedFile->getError() === \UPLOAD_ERR_OK) {
            // do something...
        }
    }
});

Validating Uploaded Files

Consider, for example, uploading images:

$pictures = $req->getUploadedFiles();
    
foreach ($pictures['uploaded_files'] as $picture) {
    // was there an error uploading?
    if (($err = $picture->getError()) !== \UPLOAD_ERR_OK) {
        throw new \Exception("There was an error `$err` while uploading picture(s)!");
    }
    // is the image size greater than 5mb (5242880 bytes)?
    else if ($picture->getSize() > 5242880) {
        throw new \RuntimeException('File size limit exceeded!');
    }
    // is the image in an unacceptable format?
    else if (! in_array(
        exif_imagetype($picture->getStream()->getMetadata('uri')), 
        [IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_GIF]
    )) {
        throw new \Exception("Sorry, but the selected image format is not allowed!");
    }
}

Moving Uploaded Files

The \Psr\Http\Message\UploadedFileInterface supports some useful methods to work on the uploaded files. We could use these methods to move the uploaded file to a new directory like so:

$files = $request->getUploadedFiles();
// assuming single file is uploaded with the key 'uploaded_file'
$uploadedFile = $files['uploaded_file'];

// create encoded file name
$extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
$basename = bin2hex(random_bytes(8));
$filename = sprintf('%s.%0.8s', $basename, $extension);

$directory = __DIR__ . '/uploads';

$uploadedFile->moveTo($directory . DIRECTORY_SEPARATOR . $filename);

Comments

Let us know if you have something to say or add