Uploading files using POST forms

Files that are uploaded using forms in POST requests can be retrieved with the Request method getUploadedFiles().

When uploading files using a POST request, make sure your file upload form has theattribute enctype="multipart/form-data" otherwise getUploadedFiles() will return an empty array.

If multiple files are uploaded for the same input name, add brackets after the input name in the HTML, otherwiseonly one uploaded file will be returned for the input name by getUploadedFiles().

Below is an example HTML form that contains both single and multiple file uploads.

  1. <!-- make sure the attribute enctype is set to multipart/form-data -->
  2. <form method="post" enctype="multipart/form-data">
  3. <!-- upload of a single file -->
  4. <p>
  5. <label>Add file (single): </label><br/>
  6. <input type="file" name="example1"/>
  7. </p>
  8. <!-- multiple input fields for the same input name, use brackets -->
  9. <p>
  10. <label>Add files (up to 2): </label><br/>
  11. <input type="file" name="example2[]"/><br/>
  12. <input type="file" name="example2[]"/>
  13. </p>
  14. <!-- one file input field that allows multiple files to be uploaded, use brackets -->
  15. <p>
  16. <label>Add files (multiple): </label><br/>
  17. <input type="file" name="example3[]" multiple="multiple"/>
  18. </p>
  19. <p>
  20. <input type="submit"/>
  21. </p>
  22. </form>
Figure 1: Example HTML form for file uploads

Uploaded files can be moved to a directory using the moveTo method. Below is an example applicationthat handles the uploaded files of the HTML form above.

  1. <?php
  2. use DI\Container;
  3. use Psr\Http\Message\ServerRequestInterface;
  4. use Psr\Http\Message\ResponseInterface;
  5. use Slim\Factory\AppFactory;
  6. require __DIR__ . '/../vendor/autoload.php';
  7. $container = new Container();
  8. $container->set('upload_directory', __DIR__ . '/uploads');
  9. AppFactory::setContainer($container);
  10. $app = AppFactory::create();
  11. $app->post('/', function(Request $request, Response $response) {
  12. $directory = $this->get('upload_directory');
  13. $uploadedFiles = $request->getUploadedFiles();
  14. // handle single input with single file upload
  15. $uploadedFile = $uploadedFiles['example1'];
  16. if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
  17. $filename = moveUploadedFile($directory, $uploadedFile);
  18. $response->write('uploaded ' . $filename . '<br/>');
  19. }
  20. // handle multiple inputs with the same key
  21. foreach ($uploadedFiles['example2'] as $uploadedFile) {
  22. if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
  23. $filename = moveUploadedFile($directory, $uploadedFile);
  24. $response->write('uploaded ' . $filename . '<br/>');
  25. }
  26. }
  27. // handle single input with multiple file uploads
  28. foreach ($uploadedFiles['example3'] as $uploadedFile) {
  29. if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
  30. $filename = moveUploadedFile($directory, $uploadedFile);
  31. $response->write('uploaded ' . $filename . '<br/>');
  32. }
  33. }
  34. return $response;
  35. });
  36. /**
  37. * Moves the uploaded file to the upload directory and assigns it a unique name
  38. * to avoid overwriting an existing uploaded file.
  39. *
  40. * @param string $directory directory to which the file is moved
  41. * @param UploadedFileInterface $uploaded file uploaded file to move
  42. * @return string filename of moved file
  43. */
  44. function moveUploadedFile($directory, UploadedFileInterface $uploadedFile)
  45. {
  46. $extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
  47. $basename = bin2hex(random_bytes(8)); // see http://php.net/manual/en/function.random-bytes.php
  48. $filename = sprintf('%s.%0.8s', $basename, $extension);
  49. $uploadedFile->moveTo($directory . DIRECTORY_SEPARATOR . $filename);
  50. return $filename;
  51. }
  52. $app->run();
Figure 2: Example Slim application to handle the uploaded files