Using PSR-7 UploadedFileInterface with zend-filter’s File and zend-validator’s File in zend-form instance
The latest zend-filter:^2.9 and zend-validator:^2.12 have full support for PSR-7 UploadedFileInterface handling. If we are using it with zend-form instance:
use Zend\Diactoros\StreamFactory; use Zend\Diactoros\UploadedFileFactory; use Zend\Filter\File\RenameUpload; use Zend\Validator\File\Size; // ... public function getInputFilterSpecification() { return [ [ 'name' => 'filename', 'required' => true, 'filters' => [ [ 'name' => RenameUpload::class, 'options' => [ 'target' => \getcwd() . '/public/uploads', 'use_upload_extension' => true, 'use_upload_name' => true, 'overwrite' => true, 'randomize' => true, 'stream_factory' => new StreamFactory(), 'upload_file_factory' => new UploadedFileFactory(), ], ], ], 'validators' => [ [ 'name' => Size::class, 'options' => [ 'max' => '10MB', ], ], ], ], ]; } // ...
The only config that needed to be changed is in the filters: the stream_factory
and upload_file_factory
config with provide objects of class that implements Psr\Http\Message\StreamFactoryInterface
and Psr\Http\UploadedFileFactoryInterface
, which if we are using zend-diactoros
, we can use Zend\Diactoros\StreamFactory
and Zend\Diactoros\UploadedFileFactory
.
For Form set data, we can now do the following:
use Psr\Http\Message\ServerRequestInterface; // ... // $request is an object of class implements ServerRequestInterface $postAndFileData = \array_merge_recursive( $request->getParsedBody(), $request->getUploadedFiles() ); // ...
On get data, we have different result from normal Zend\Http\Phpenvironment\Request
. If we are using normal Zend\Http\Phpenvironment\Request
, we normally get the following data:
array (size=1) 'filename' => array (size=5) 'name' => string 'Untitled-1.png' (length=14) 'type' => string 'image/png' (length=9) 'size' => int 761087 'tmp_name' => string '/path/to/public/uploads/Untitled-1_5c51c49e1d0855_97287659.png' (length=103) 'error' => int 0
With the new parameters, the form data will be:
array (size=1) 'filename' => object(Zend\Diactoros\UploadedFile)[966] private 'clientFilename' => string 'Untitled-1.png' (length=14) private 'clientMediaType' => string 'image/png' (length=9) private 'error' => int 0 private 'file' => null private 'moved' => boolean false private 'size' => int 761087 private 'stream' => object(Zend\Diactoros\Stream)[967] protected 'resource' => resource(12, stream) protected 'stream' => string '/path/to/public/uploads/Untitled-1_5c51c49e1d0855_97287659.png' (length=103)
We can consume the file uploaded data from Zend\Diactoros\UploadedFile
‘s functions, or we want a array
data, we can loop the fields recursively and convert to array
data whenever the value is instanceof Psr\Http\Message\UploadedFileInterface
, eg:
use Psr\Http\Message\UploadedFileInterface; // ... $data = $form->getData(); \array_walk_recursive($data, function (& $value) { if ($value instanceof UploadedFileInterface) { $value = [ 'name' => $value->getClientFilename(), 'type' => $value->getClientMediaType(), 'size' => $value->getSize(), 'tmp_name' => $value->getStream()->getMetadata('uri'), 'error' => $value->getError(), ]; } }); // ...
The data are now completely an array so we are safe to use in another use case, eg: save to temporary session for File PRG use case.
Tinify : Resize your image without reduce quality
I tried some client library services for my project to resize images. They resized images correctly, however, they made the images quality slightly reduced. Until my client suggested me to try Tinify API service, that the API key I can just use, and it works pretty well.
The Tinify provide free 500 compresions per-month if you need to try. You can upgrade to paid account if you need more. To register, you can go to https://tinypng.com/developers and got the following page and fill your name and email and click “Get your API key”:
You can then check your email to get the link and be redirected to the dashboard page with information of your API key and how many compressions left for current month:
There are libraries for different languages, for example, if you are using PHP, you can use tinify-php that you can require via composer in your project by run:
$ composer require tinify/tinify
Once required, you can do :
include 'vendor/autoload.php'; \Tinify\setKey('YOUR_API_KEY'); // fill with your API key $source = \Tinify\fromFile('/path/to/file.png'); // source file $resized = $source->resize(array( 'method' => 'scale', 'width' => 500, )); $resized->toFile('target-thumbnail.png'); // target file
For complete reference, you can look at https://tinypng.com/developers/reference/php . That’s it!
leave a comment