22

Symfony 2.1 でLiipImagineBundleを使用しており、アップロード時にユーザーがアップロードした画像のサイズを変更してから、永続的なファイルシステムの場所に保存したいと考えています (メタデータを削除し、jpeg 形式を強制し、ファイルのサイズを制限するため)。コントローラーから「ストリップ」および「サイズ変更」フィルターを呼び出し、フィルター処理された画像を一時的な場所からファイルシステムで選択したフォルダーに保存する必要があります。

バンドルの readme に示されているように、LiipImageBundle Controller をサービスとして使用しようとしましたただし、呼び出されたアクションは主に、画像を表示する要求が行われたときにキャッシュ ディレクトリにフィルター処理された画像を作成するためのものです (アップロード中のフィルター処理に使用することは別のケースです)。とにかく次のように実装しようとしましたが、うまくいきました。フィルタを適用できるようにするには、最初にファイルを Web サーバーの php 一時ディレクトリから Web フォルダ内のディレクトリに移動する必要がありました。次に、フィルターを適用し、フィルター処理されていない最初のファイルを削除 (unlink()) しました。最後に、フィルター処理されたファイルをファイル システム内の永続的な場所に移動 (rename()) する必要がありました。すべてを機能させるには、ファイルを 2 回移動し、フィルターを 1 回適用し、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 に答える
0

この問題を正確に解決するバンドルを作成しました。ORM のライフサイクル コールバックをVichUploaderBundle使用して簡単にアップロードできますLiipImagineが、サイズ変更にも優れています。

これがその組み合わせです: https://github.com/RSSfeed/VichImagineBundle

わずか数分で実装する方法については、短い readmeを参照してください。

于 2016-11-08T22:24:22.527 に答える
0

より良い方法が見つからなかったため、質問の説明に記載されている解決策を保持しました。このソリューションは、パフォーマンスの観点からは最適とは思えませんが (ファイルを 2 回移動し、フィルターを 1 回適用し、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 に答える