2013-02-24 2 views
15

Я использую LiipImagineBundle с Symfony 2.1 и хотел бы изменить размер загруженных пользователем изображений при загрузке, прежде чем сохранять их в постоянное местоположение файловой системы (чтобы разбить метаданные, наложить формат jpeg и ограничить размер файла). Мне нужно вызвать фильтр «strip» и «resize» из контроллера, а затем сохранить отфильтрованное изображение из временного местоположения в папку по своему выбору в файловой системе.Использование LiipImagineBundle для изменения размера изображения после загрузки?

Я попытался использовать LiipImageBundle Controller as a service as indicated in the bundle's readme, но вызываемое действие предназначено в основном для создания отфильтрованного изображения в каталоге кеша, когда запрос на отображение изображения (его использование для фильтрации при загрузке - это еще один случай). Я попытался реализовать его в любом случае, и получил его на работу. Я должен был сначала перенести файл из временного каталога php веб-сервера в каталог в веб-папке, чтобы иметь возможность применить фильтр. Во-вторых, я применил фильтр и удалил (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); 
    } 
} 

Мой фильтр в приложение/Config/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

ли вы когда-нибудь найти лучшее решение? Я тоже хочу этого. Фильтр работает хорошо, но производительность невелика, когда у меня много эскизов, перемещение их из кеша в известное место при загрузке ускоряет работу. –

+0

@PeterWooster: Я не нашел другого решения, но описанное выше, похоже, работает нормально (я сохранил его таким образом). – RayOnAir

+0

Я работаю над решением и опубликую здесь, когда он работает. –

ответ

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

+0

+1: Вы определили правильные услуги, чтобы применить фильтр и сохранить преобразованное изображение в нужное место назначения. Полный ответ на мой вопрос - это сочетание моих шагов по сохранению временного изображения в файловой системе и ваших шагов по применению фильтра и сохранению преобразованного изображения в конечный пункт назначения (поскольку мой вопрос заключается в применении фильтра непосредственно к загруженному изображению для его изменения, прежде чем сохранять его в файловой системе). Ваше решение предназначено для создания миниатюр и хранения их из образа, уже находящегося в файловой системе. – RayOnAir

+0

Обратите внимание, что не представляется возможным применить фильтр к изображению, которое еще не находится в папке где-то в веб-каталоге, если не установлены специальные права доступа. – RayOnAir

0

Учитывая, что я не нашел лучшего способа, я сохранил решение, описанное в описании вопроса. Это решение не кажется оптимальным с точки зрения производительности (требуется дважды переместить файл, применить фильтр один раз и отсоединить 1 файл), но он выполняет задание.

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. –

7

Модифицированная версия @Peter Wooster, и сделала ее более общей, поэтому, если кто-то использует ее без объекта изображения, он может легко взять на себя Benifet. Я даю здесь две версии, которые можно использовать в классе служебных или неконтролируемых. И другая версия предназначена для классов контроллера. Теперь вам решать, где вам нравится :)

Использовать вне контроллера, например. хранение его в служебных помещениях

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

Im get the follwoing error при попытке вашего кода на стеке bitnami wamp, тип mime загрузки изображений/файлы/img-5535_05052015_923_c2a1a.JPG должен быть image/xxx got inode/x-empty. Вы можете помочь мне с этим? – Adam

+0

@Adam попробуйте загрузить некоторые другие изображения и с каким-то другим типом, так как тип mime изображения выглядит поврежденным или имеет некоторые другие проблемы. –

0

Я написал комплект, который точно решает эту проблему.В то время как VichUploaderBundle обеспечивает легкую загрузку с использованием обратных вызовов LFecycle ORM, LiipImagine отлично справляется с изменением размера.

Вот сочетание этого: https://github.com/RSSfeed/VichImagineBundle

Смотрите short readme о том, как осуществить это всего несколько минут.

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 
Смежные вопросы