22

我正在将LiipImagineBundle与 Symfony 2.1 一起使用,并希望在上传时调整用户上传的图像大小,然后再将它们保存到永久文件系统位置(去除元数据、强制 jpeg 格式并限制文件的大小)。我必须从控制器调用“条带”和“调整大小”过滤器,然后将过滤后的图像从临时位置保存到我在文件系统中选择的文件夹中。

我尝试将LiipImageBundle 控制器用作捆绑包自述文件中所示的服务但是被调用的Action主要是为了在请求显示图像时在缓存目录中创建一个过滤后的图像(在上传过程中使用它进行过滤是另一种情况)。无论如何,我尝试按如下方式实现它,并让它工作。我必须首先将文件从 web 服务器的 php 临时目录移动到 web 文件夹中的目录才能应用过滤器。其次,我应用了过滤器并删除了(unlink())初始未过滤的文件。最后,我必须将过滤后的文件移动(重命名())到文件系统中的永久位置。必须移动文件两次,应用过滤器一次,然后删除(取消链接)1 个文件以使其全部工作。有没有更好的方法(不需要中间移动)在上传时使用捆绑包?

class MyController extends Controller
{
    public function new_imageAction(Request $request)
    {
        $uploadedFile = $request->files->get('file');
        $tmpFolderPathAbs = $this->get('kernel')->getRootDir() . '/../web/uploads/tmp/';
        $tmpImageNameNoExt = rand();
        $tmpImageName = $tmpImageNameNoExt . '.' . $fileExtension;
        $uploadedFile->move($tmpFolderPathAbs, $tmpImageName);
        $tmpImagePathRel = '/uploads/tmp/' . $tmpImageName;
        // Create the filtered image in a tmp folder:
        $this->container->get('liip_imagine.controller')->filterAction($request, $tmpImagePathRel, 'my_filter');
        unlink($tmpFolderPathAbs . $tmpImageName);
        $filteredImagePathAbs = $this->get('kernel')->getRootDir() . '/../web/uploads/cache/my_filter/uploads/tmp/' . $tmpImageNameNoExt . '.jpeg';
        $imagePath = $imageManagerResponse->headers->get('location');
        // define permanent location ($permanentImagePathAbs)...
        rename($filteredImagePathAbs, $permanentImagePathAbs);
    }
}

我在 app/config/config.yml 中的过滤器如下:

liip_imagine:
    filter_sets:
        my_filter:
            format: jpeg
            filters:
                strip: ~
                thumbnail: { size: [1600, 1000], mode: inset }

有人对 ImagineAvalancheBundle 提出了类似的问题,但没有给出太多细节。也许从此处提供的列表中实施另一项服务是更好的解决方案?

4

5 回答 5

19

所以这是一种在上传时使用 LiipImagineBundle 创建缩略图的方法。诀窍是使用他们的一些其他服务:

    /**
     * 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
    }

如果您没有其他理由包含 LiipImagineBundle,这也可以通过直接调用 Imagine 库函数来完成。将来我可能会对此进行研究,但这适用于我的情况并且表现非常好。

于 2013-03-27T20:51:32.547 回答
9

@Peter Wooster 的修改版本,使其更通用,因此如果有人在没有图像实体的情况下使用它,他/她可以轻松地从中受益。我在这里给出了两个版本,一个可以保存在实用程序或非控制器类中。另一个版本用于控制器类。现在由你决定你喜欢的地方:)

在控制器外部使用,例如将其保存在实用程序类中

/**
 * 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
}

在控制器中使用,例如 CommonController 或任何其他控制器。

/**
 * 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
}
于 2014-07-01T13:04:24.213 回答
1

不要使用 liip 数据管理器加载文件,而是从上传的文件创建 liip 二进制对象:

use Liip\ImagineBundle\Model\Binary;

然后使用以下代码:

                // 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
于 2017-07-02T10:42:54.203 回答
0

鉴于我没有找到更好的方法,我保留了问题描述中描述的解决方案。从性能的角度来看,该解决方案似乎不是最佳解决方案(它需要移动文件两次,应用过滤器一次,然后取消链接 1 个文件),但它完成了工作。

更新:

我更改了我的代码以使用 Peter Wooster 的回答中指示的服务,如下所示(该解决方案更优化,因为过滤后的图像直接保存到最终目的地):

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);
    }
}
于 2013-03-01T22:40:18.883 回答
0

我写了一个包来解决这个问题。虽然VichUploaderBundle使用 ORM 的生命周期回调提供了轻松的上传,LiipImagine但在调整大小方面做得很好。

这是它的组合:https ://github.com/RSSfeed/VichImagineBundle

请参阅有关如何在几分钟内实现它的简短自述文件。

于 2016-11-08T22:24:22.527 回答