Developing software in the Real World

PSR-7 file uploads in Slim 3

Handling file uploads in Slim 3 is reasonably easy as it uses the PSR-7 Request object, so let's take a look.

The easiest way to get a Slim framework project up and running is to use the Slim-Skeleton to create a project:

and then you can cd into the directory and run the PHP built-in web server using:

Displaying the form

We can now create a simple form, firstly by setting up the / route in src/routes.php:

The view script, templates/index.phtml contains the form:

Handling the upload

We now need to write the route that handles the uploaded file. This goes in src/routes.php:

The file upload in $_FILES is available from the $request's getUploadedFiles() method. This returns an array keyed by the name of the <input> element. In this case, that's newfile.

The $newfile object is a instance of PSR-7's UploadedFileInterface. Typical usage is to check that there is no error and then move the file to somewhere else. This is done like this:

There's also other useful methods such as getClientMediaType() and getSize() if you need them.

Conclusion

As you can see, dealing with file uploads within a PSR-7 request is really easy!

11 thoughts on “PSR-7 file uploads in Slim 3

  1. Just in case, someone want to upload their file to other services, let say Cloudinary, etc. They can simply use $newFile->file┬┤ property to get the content of $_FILES['…']['tmpname']┬┤

  2. Thanks for example.
    I think $this->file in Slim\Http\UploadedFile.php should be protected and public method e.g getUploadedPath() { return $this->file; } should be added.

  3. Hi Rob,

    Nice article, however I get the following error when the moveTo is called:
    {
    "message": "Slim Application Error",
    "exception": [
    {
    "type": "RuntimeException",
    "code": 0,
    "message": "Could not write to stream",
    "file": "\/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/Http\/Stream.php",
    "line": 384,
    "trace": [
    "#0 \/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/Http\/Response.php(258): Slim\\Http\\Stream->write(Array)",
    "#1 \/home\/johan\/web\/skeleton\/src\/routes.php(142): Slim\\Http\\Response->write(Array)",
    "#2 [internal function]: Closure->{closure}(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response), Array)",
    "#3 \/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/Handlers\/Strategies\/RequestResponse.php(41): call_user_func(Object(Closure), Object(Slim\\Http\\Request), Object(Slim\\Http\\Response), Array)",
    "#4 \/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/Route.php(325): Slim\\Handlers\\Strategies\\RequestResponse->__invoke(Object(Closure), Object(Slim\\Http\\Request), Object(Slim\\Http\\Response), Array)",
    "#5 \/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/MiddlewareAwareTrait.php(116): Slim\\Route->__invoke(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))",
    "#6 \/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/Route.php(297): Slim\\Route->callMiddlewareStack(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))",
    "#7 \/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/App.php(434): Slim\\Route->run(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))",
    "#8 \/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/MiddlewareAwareTrait.php(116): Slim\\App->__invoke(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))",
    "#9 \/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/App.php(341): Slim\\App->callMiddlewareStack(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))",
    "#10 \/home\/johan\/web\/skeleton\/vendor\/slim\/slim\/Slim\/App.php(302): Slim\\App->process(Object(Slim\\Http\\Request), Object(Slim\\Http\\Response))",
    "#11 \/home\/johan\/web\/skeleton\/public\/index.php(30): Slim\\App->run()",
    "#12 {main}"
    ]
    }
    ]
    }

    Regards,
    Johan

  4. I seem to be getting a an error on "call to member function getError on null" any ideas on what I am doing wrong?

Leave a Reply

Your email address will not be published. Required fields are marked *