Use LiipImagineBundle to Resize Image after Upload?

寵の児 提交于 2019-11-27 19:08:12

So here's a way to create thumbnails at upload with LiipImagineBundle. The trick is to use some of their other services:

    /**
     * Write a thumbnail image using the LiipImagineBundle
     * 
     * @param Document $document an Entity that represents an image in the database
     * @param string $filter the Imagine filter to use
     */
    private function writeThumbnail($document, $filter) {
        $path = $document->getWebPath();                                // domain relative path to full sized image
        $tpath = $document->getRootDir().$document->getThumbPath();     // absolute path of saved thumbnail

        $container = $this->container;                                  // the DI container
        $dataManager = $container->get('liip_imagine.data.manager');    // the data manager service
        $filterManager = $container->get('liip_imagine.filter.manager');// the filter manager service

        $image = $dataManager->find($filter, $path);                    // find the image and determine its type
        $response = $filterManager->get($this->getRequest(), $filter, $image, $path); // run the filter 
        $thumb = $response->getContent();                               // get the image from the response

        $f = fopen($tpath, 'w');                                        // create thumbnail file
        fwrite($f, $thumb);                                             // write the thumbnail
        fclose($f);                                                     // close the file
    }

This could also be done by directly calling the Imagine library functions if you had no other reason to include the LiipImagineBundle. I'll probably look into that in the future, but this works for my case and performs very well.

Modified version of @Peter Wooster, and made it more generic so if someone is using it without Image entity he/she can easily take benifet from it. I'm giving here two versions, one that can be used kept in utility or non-controller class. And the other version is for controller classes. It's up to you now where you like :)

To use outside of controller e.g. keeping it in utility classes

/**
 * Write a thumbnail image using the LiipImagineBundle
 * 
 * @param Document $fullSizeImgWebPath path where full size upload is stored e.g. uploads/attachments
 * @param string $thumbAbsPath full absolute path to attachment directory e.g. /var/www/project1/images/thumbs/
 * @param string $filter filter defined in config e.g. my_thumb
 * @param Object $diContainer Dependency Injection Object, if calling from controller just pass $this
 */
public function writeThumbnail($fullSizeImgWebPath, $thumbAbsPath, $filter, $diContainer) {
    $container = $diContainer; // the DI container, if keeping this function in controller just use $container = $this
    $dataManager = $container->get('liip_imagine.data.manager');    // the data manager service
    $filterManager = $container->get('liip_imagine.filter.manager'); // the filter manager service
    $image = $dataManager->find($filter, $fullSizeImgWebPath);                    // find the image and determine its type
    $response = $filterManager->applyFilter($image, $filter);

    $thumb = $response->getContent();                               // get the image from the response

    $f = fopen($thumbAbsPath, 'w');                                        // create thumbnail file
    fwrite($f, $thumb);                                             // write the thumbnail
    fclose($f);                                                     // close the file
}

To use in controller e.g. CommonController or any other controller.

/**
 * Write a thumbnail image using the LiipImagineBundle
 * 
 * @param Document $fullSizeImgWebPath path where full size upload is stored e.g. uploads/attachments
 * @param string $thumbAbsPath full absolute path to attachment directory e.g. /var/www/project1/images/thumbs/
 * @param string $filter filter defined in config e.g. my_thumb
 */
public function writeThumbnail($fullSizeImgWebPath, $thumbAbsPath, $filter) {
    $container = $this->container;
    $dataManager = $container->get('liip_imagine.data.manager');    // the data manager service
    $filterManager = $container->get('liip_imagine.filter.manager'); // the filter manager service
    $image = $dataManager->find($filter, $fullSizeImgWebPath);                    // find the image and determine its type
    $response = $filterManager->applyFilter($image, $filter);

    $thumb = $response->getContent();                               // get the image from the response

    $f = fopen($thumbAbsPath, 'w');                                        // create thumbnail file
    fwrite($f, $thumb);                                             // write the thumbnail
    fclose($f);                                                     // close the file
}

Instead of loading the file using liip data manager, create liip binary object from the uploaded file:

use Liip\ImagineBundle\Model\Binary;

then use the following code:

                // Generate a unique name for the file before saving it
                $fileName = md5(uniqid()) . '.' . $uploadedFile->guessExtension();

                $contents = file_get_contents($uploadedFile);

                $binary = new Binary(
                    $contents,
                    $uploadedFile->getMimeType(),
                    $uploadedFile->guessExtension()
                );

                $container = $this->container;
                $filterManager = $container->get('liip_imagine.filter.manager');    // the filter manager service
                $response = $filterManager->applyFilter($binary, 'my_thumb');

                $thumb = $response->getContent();                               // get the image from the response

                $f = fopen($webRootDir .'/images_dir/' . $fileName, 'w');                                        // create thumbnail file
                fwrite($f, $thumb);                                             // write the thumbnail
                fclose($f);                                                     // close the file

Given that I did not find a better way, I kept the solution described in the question description. That solution does not seem the optimal one from a performance stand point (it requires moving the file twice, apply the filter once, and unlink 1 file), but it gets the job accomplished.

UPDATE:

I changed my code to use the services indicated in Peter Wooster's answer, as shown below (that solution is more optimal as the filtered image is saved directly to the final destination):

class MyController extends Controller
{
    public function new_imageAction(Request $request)
    {
        $uploadedFile = $request->files->get('file');
        // ...get file extension and do other validation...
        $tmpFolderPathAbs = $this->get('kernel')->getRootDir() . '/../web/uploads/tmp/'; // folder to store unfiltered temp file
        $tmpImageNameNoExt = rand();
        $tmpImageName = $tmpImageNameNoExt . '.' . $fileExtension;
        $uploadedFile->move($tmpFolderPathAbs, $tmpImageName);
        $tmpImagePathRel = '/uploads/tmp/' . $tmpImageName;
        // Create the filtered image:
        $processedImage = $this->container->get('liip_imagine.data.manager')->find('my_filter', $tmpImagePathRel);
        $filteredImage = $this->container->get('liip_imagine.filter.manager')->get($request, 'my_filter', $processedImage, $tmpImagePathRel)->getContent();
        unlink($tmpFolderPathAbs . $tmpImageName); // eliminate unfiltered temp file.
        $permanentFolderPath = $this->get('kernel')->getRootDir() . '/../web/uploads/path_to_folder/';
        $permanentImagePath = $permanentFolderPath . 'my_image.jpeg';
        $f = fopen($permanentImagePath, 'w');
        fwrite($f, $filteredImage); 
        fclose($f);
    }
}

I've written a bundle that solves exact this problem. While VichUploaderBundle provides easy uploading using ORM's Lifecycle callbacks, LiipImagine does a great job at resizing.

Here is the combination of it: https://github.com/RSSfeed/VichImagineBundle

See the short readme on how to implement it in only few minutes.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!