2013-02-24 104 views
15

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

我试图使用LiipImageBundle Controller as a service as indicated in the bundle's readme,但被调用的Action主要用于在请求显示图像(在上传过程中使用它进行过滤时是另一种情况)时在缓存目录中创建过滤图像。无论如何,我试图按照如下方式实施它,并将其付诸实施。我必须首先将文件从Web服务器的php临时目录移动到Web文件夹中的目录才能应用过滤器。其次,我应用过滤器并删除(取消链接())最初的未过滤文件。最后,我必须将过滤的文件移动(重命名())到文件系统中的永久位置。有必要移动文件两次,应用一次过滤器,并删除(取消链接)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.yml滤波器如下:

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

A similar question was asked for the ImagineAvalancheBundle但没有太多的细节中给出。也许实施another service from the here provided list是更好的解决方案?

+0

你有没有找到一个更好的解决办法?我也想要这个。过滤器运行良好,但是当我有很多缩略图时,性能并不是很好,在上传时将它们从缓存移动到已知位置会显着加快速度。 – 2013-03-27 08:50:53

+0

@PeterWooster:我没有找到另一个解决方案,但上面描述的解决方案似乎工作正常(我保持这种方式)。 – RayOnAir 2013-03-27 16:11:53

+0

我正在研究解决方案,并在工作时发布。 – 2013-03-27 18:12:13

回答

16

所以,这里有一个使用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畅想库函数来完成。我可能会在未来考虑这一点,但这对我的情况很有效,并且表现非常好。

+0

感谢您发表该答案。只要我有一点时间来尝试它,我会让你知道它是怎么回事! – RayOnAir 2013-04-02 22:23:23

+0

+1:您确定了正确的服务以应用过滤器并将转换后的图像保存到所需的目的地。我的问题的完整答案是我将临时图像保存到文件系统的步骤和应用过滤器并将转换后的图像保存到最终目的地的步骤的组合(因为我的问题是直接在上传的图像上应用过滤器在将其保存到文件系统之前调整它的大小)。您的解决方案是用于创建缩略图并从已存在于文件系统中的映像中存储它们。 – RayOnAir 2013-04-03 00:29:35

+0

请注意,除非设置了特殊访问权限,否则将过滤器应用于尚未位于Web目录中某个文件夹中的图像似乎不可能。 – RayOnAir 2013-04-03 00:34:24

0

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

UPDATE:

我改变了我的代码使用在彼得·伍斯特的回答表明了服务,如下图所示(如过滤后的图像直接保存到最终目的地的解决方案是更优化):

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); 
    } 
} 
+0

你可以写一个服务来完成整个事情,然后使用它来代替LiipImagine。 – 2013-06-05 12:36:33

7

@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 
} 
+0

在我的bitnami wamp stack上尝试你的代码时,我得到了follwoing错误,MIME类型的图像uploads/files/img-5535_05052015_923_c2a1a.JPG必须是image/xxx inode/x-empty。 你能帮我吗? – Adam 2015-05-05 11:40:16

+0

@亚当尝试上传一些其他图像,以及其他类型,因为图像MIME类型看起来损坏或有其他一些问题。 – 2015-05-05 12:23:29

0

不必加载使用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