PSR-7 Standard – Part 4 – File Uploads

PSR-7 Standard – Part 4 – File Uploads

This post is part of series:


After we learned what a Request and a Response are, let’s now look how we can send files to the server. Then have a look on how we can process them with Guzzle on the server side.

Client Side Script

As you can see in the diagram, a file upload is also handled as stream.

First we create script “file_upload.php” with this content which initializes the autoloader and creates a sample file for the upload test.

<?php
require_once 'vendor/autoload.php';
  
// create a test file
file_put_contents('foo.txt', '"Foo" is the content of the file');

After we have a text file, we can create our stream with the Guzzle PSR-7 component. Please add the code to the existing file.

// put test file into multipart stream
$multipart = new \GuzzleHttp\Psr7\MultipartStream([
    [
        'name' => 'upload_file',
        'contents' => fopen('foo.txt', 'r')
    ],
]);

The MultipartStream gives us the ability to send more than once file to the server. As last part of the script we need to create a Request to send the MultipartStream to the server.

$request = new \GuzzleHttp\Psr7\Request('POST', 'http://127.0.0.1:8080');
$request = $request->withBody($multipart);

$client = new \GuzzleHttp\Client();
$response = $client->send($request);
echo $response->getBody();

Server Side Script

Please create the script “server_file.php” to receive the files.

<?php

require_once __DIR__ . '/vendor/autoload.php';

$request = \GuzzleHttp\Psr7\ServerRequest::fromGlobals();
$files = $request->getUploadedFiles();

$response = new \GuzzleHttp\Psr7\Response();
$response = $response->withStatus(200, 'OK');

$uploadedFiles = $request->getUploadedFiles();

$uploadedFileInfos = [];
foreach ($uploadedFiles as $uploadedFile) {
    /** @var $uploadedFile \GuzzleHttp\Psr7\UploadedFile */
    $uploadedFileInfos[] = [
        'file_name' => $uploadedFile->getClientFilename(),
        'mime_type' => $uploadedFile->getClientMediaType(),
        'size'      => $uploadedFile->getSize(),
        'content'   => (string) $uploadedFile->getStream()
    ];
}

$response = $response->withBody(
    \GuzzleHttp\Psr7\stream_for(print_r($uploadedFileInfos))
);

echo \GuzzleHttp\Psr7\str($response);

The script is very simple. It creates a ServerRequest (we talk about this in a future blog post). The ServerRequest can handle the MultipartStream and return the files with the handy method method getUploadedFiles. This methods is now a standard to get all data of the uploaded files. If you know how files are handled without PSR-7 you know that this is a really enhancement.

For debugging we collect all data of the uploaded files and return them back as response to the client.

Test the Upload

Run the server in console:

php -S 127.0.0.1:8080 server_file.php

Run the client script in a second console:

php file_upload.php

If you did everything correct you should now see the result of the server script:

HTTP/1.1 200 OK

Array
(
    [0] => Array
        (
            [file_name] => foo.txt
            [mime_type] => text/plain
            [size] => 32
            [content] => "Foo" is the content of the file
        )

)

 

That’s it. The next blog post will give you some inside into the HTTP Client.

Leave a Reply

%d bloggers like this: