Welcome to Abdul Malik Ikhsan's Blog

Using PSR-7 UploadedFileInterface with zend-filter’s File and zend-validator’s File in zend-form instance

Posted in expressive, Tutorial PHP, Zend Framework by samsonasik on February 3, 2019

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

Posted in php, Teknologi, tips and tricks by samsonasik on February 3, 2019

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!