我正在使用LiipImagineBundle和Symfony 2.1,并希望在上传后调整用户上传的图像大小,然后将其保存到永久文件系统位置(删除元数据,强制使用jpeg格式,并限制文件大小) )。我必须从控制器调用'strip'和'resize'过滤器,然后将过滤后的图像从临时位置保存到我在文件系统中选择的文件夹中。
我尝试使用LiipImageBundle Controller as a service as indicated in the bundle's readme但是被调用的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 }
A similar question was asked for the ImagineAvalancheBundle但没有提供太多细节。也许实施another service from the here provided list是一个更好的解决方案?
答案 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,也可以通过直接调用Imagine库函数来完成。我可能会在将来对此进行研究,但这适用于我的情况并且表现非常好。
答案 1 :(得分:8)
@Peter Wooster的修改版本,并使其更通用,所以如果有人在没有Image实体的情况下使用它,他/她可以轻松地从中获取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
}
答案 2 :(得分: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);
}
}
答案 3 :(得分:0)
我写了一个解决了这个问题的捆绑包。虽然VichUploaderBundle
可以使用ORM的生命周期回调轻松上传,但LiipImagine
在调整大小方面做得很好。
以下是它的组合:https://github.com/RSSfeed/VichImagineBundle
只需几分钟即可查看short readme如何实现它。
答案 4 :(得分: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