Magento 2: Comment obtenir une image redimensionnée pour un module personnalisé?

12

J'utilise Magento 2 CE version 2.1.0

J'ai un module personnalisé avec champ d'image. Quand il est téléchargé, je veux des images de tailles différentes comme pour le produit, nous avons une image miniature, une image de liste et une image de page de détail du produit.

Capable de télécharger 1 image sans redimensionner.

J'utilise le code ci-dessous pour redimensionner l'image, mais cela donne l'URL de l'image du produit. Pas mon module personnalisé.

\ app \ code \ Custom \ Module \ Block \ MyPosts \ Edit.php

public function getImage($posts, $image) {
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $_imagehelper = $objectManager->get('Magento\Catalog\Helper\Image');
    echo $postImage = $_imagehelper->init($posts, $image)->constrainOnly(FALSE)->keepAspectRatio(TRUE)->keepFrame(FALSE)->resize(400)->getUrl();
    exit;
}

Il donne l'URL ci-dessous http: //localhost/magento2/pub/static/frontend/Magento/luma/en_US/Magento_Catalog/images/product/placeholder/.jpg

Mon image est stockée ici: \magento2\pub\media\custom_module\posts\image.

Comment puis-je obtenir redimensionner l'image avec ce chemin et comment puis-je enregistrer / récupérer une image de taille différente?

Ankit Shah
la source

Réponses:

15

Vous pouvez vérifier les détails en cliquant sur, Redimensionner l'image personnalisée dans Magento 2

À l'intérieur du fichier de blocage, conservez le code ci-dessous,

   protected $_filesystem ;
   protected $_imageFactory;
   public function __construct(            
        \Magento\Framework\Filesystem $filesystem,         
        \Magento\Framework\Image\AdapterFactory $imageFactory         
        ) {         
        $this->_filesystem = $filesystem;               
        $this->_imageFactory = $imageFactory;         
        }

    // pass imagename, width and height
    public function resize($image, $width = null, $height = null)
    {
        $absolutePath = $this->_filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA)->getAbsolutePath('custom_module/posts/').$image;
        if (!file_exists($absolutePath)) return false;
        $imageResized = $this->_filesystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA)->getAbsolutePath('resized/'.$width.'/').$image;
        if (!file_exists($imageResized)) { // Only resize image if not already exists.
            //create image factory...
            $imageResize = $this->_imageFactory->create();         
            $imageResize->open($absolutePath);
            $imageResize->constrainOnly(TRUE);         
            $imageResize->keepTransparency(TRUE);         
            $imageResize->keepFrame(FALSE);         
            $imageResize->keepAspectRatio(TRUE);         
            $imageResize->resize($width,$height);  
            //destination folder                
            $destination = $imageResized ;    
            //save image      
            $imageResize->save($destination);         
        } 
        $resizedURL = $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA).'resized/'.$width.'/'.$image;
        return $resizedURL;
  } 

Maintenant, appelez à l'intérieur du fichier phtml,

$block->resize('test.jpg',500,400);
Rakesh Jesadiya
la source
Bravo. Fonctionne parfaitement. Ainsi, lors de l'ajout d'une image, nous n'avons pas à télécharger avec des tailles différentes. Ce n'est qu'en affichant que nous devons gérer correctement @Rakesh?
Ankit Shah du
1
oui quand nous devons afficher à ce moment gérer.
Rakesh Jesadiya
ne fonctionne pas lorsque nous essayons de redimensionner 1 image et de la placer dans le même dossier avec la même image. comme ceci: $ absolutePath = $ this -> _ filesystem-> getDirectoryRead (\ Magento \ Framework \ App \ Filesystem \ DirectoryList :: MEDIA) -> getRelativePath ('C: / xampp / htdocs / magento / app / code / Aht / BannerSlider /view/frontend/web/').$image; $ imageResized = $ this -> _ filesystem-> getDirectoryRead (\ Magento \ Framework \ App \ Filesystem \ DirectoryList :: MEDIA) -> getRelativePath ('C: / xampp / htdocs / magento / app / code / Aht / BannerSlider / view / frontend / web /').$ image;
fudu
Comme déjà mentionné, cela ne devrait pas être la réponse acceptée. Vous n'avez pas besoin de faire tout cela vous-même - utilisez simplement l'assistant d'image déjà existant du noyau Magento.
fritzmg
@ RakeshJesadiya, ça me donne un texte inconnu comme url
Hitesh Balpande
13

La réponse acceptée ne considère pas la mise en cache de l'image pour améliorer les performances. Vous n'avez pas besoin de redimensionner et d'écraser l'image chaque fois qu'elle est demandée. L'approche suivante enregistre l'image redimensionnée dans un dossier «cache» afin que les appels successifs renvoient l'image à partir du cache. La méthode est contenue dans un assistant (pas un bloc), vous pouvez donc l'appeler à partir de n'importe quel modèle que vous aimez:

app / code / Vendeur / Espace de noms / Aide / Image.php

<?php

namespace Vendor\Namespace\Helper;

use Magento\Framework\App\Filesystem\DirectoryList;

class Image extends \Magento\Framework\App\Helper\AbstractHelper
{
    /**
     * Custom directory relative to the "media" folder
     */
    const DIRECTORY = 'custom_module/posts';

    /**
     * @var \Magento\Framework\Filesystem\Directory\WriteInterface
     */
    protected $_mediaDirectory;

    /**
     * @var \Magento\Framework\Image\Factory
     */
    protected $_imageFactory;

    /**
     * Store manager
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $_storeManager;

    /**
     * @param \Magento\Framework\App\Helper\Context $context
     * @param \Magento\Framework\Filesystem $filesystem
     * @param \Magento\Framework\Image\Factory $imageFactory
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     */
    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\Framework\Image\AdapterFactory $imageFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager
    ) {
        $this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
        $this->_imageFactory = $imageFactory;
        $this->_storeManager = $storeManager;
        parent::__construct($context);
    }

    /**
     * First check this file on FS
     *
     * @param string $filename
     * @return bool
     */
    protected function _fileExists($filename)
    {
        if ($this->_mediaDirectory->isFile($filename)) {
            return true;
        }
        return false;
    }

    /**
     * Resize image
     * @return string
     */
    public function resize($image, $width = null, $height = null)
    {
        $mediaFolder = self::DIRECTORY;

        $path = $mediaFolder . '/cache';
        if ($width !== null) {
            $path .= '/' . $width . 'x';
            if ($height !== null) {
                $path .= $height ;
            }
        }

        $absolutePath = $this->_mediaDirectory->getAbsolutePath($mediaFolder) . $image;
        $imageResized = $this->_mediaDirectory->getAbsolutePath($path) . $image;

        if (!$this->_fileExists($path . $image)) {
            $imageFactory = $this->_imageFactory->create();
            $imageFactory->open($absolutePath);
            $imageFactory->constrainOnly(true);
            $imageFactory->keepTransparency(true);
            $imageFactory->keepFrame(true);
            $imageFactory->keepAspectRatio(true);
            $imageFactory->resize($width, $height);
            $imageFactory->save($imageResized);
        }

        return $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . $path . $image;
    }
}

Maintenant, à partir de n'importe quel modèle .phtml, vous pouvez appeler la méthode comme ceci:

<!-- Get a reference to the Image helper -->
<?php $image = $this->helper('Vendor\Namespace\Helper\Image'); ?>
.
.
.
<!-- Resize the image by specifying width only -->
<img src="<?php echo $image->resize('/my-picture.jpg', 1200); ?>">

<!-- Resize the image by specifying width and height -->
<img src="<?php echo $image->resize('/my-picture.jpg', 640, 480); ?>">
Daniel Kratohvil
la source
Puis-je suggérer d'ajouter une vérification pour le fichier d'origine, au cas où il n'existerait pas? dans la fonction resize (): j'ai changé if (!$this->_fileExists($path . $image)) {pourif (!$this->_fileExists($path . $image) && $this->_fileExists($mediaFolder . $image)) {
Alexandru Bangală
Travaillez comme un charme, merci. Cela devrait être la réponse acceptée
fudu
Vous pouvez également simplement utiliser l'existant \Magento\Catalog\Helper\Image.
fritzmg
1
@fritzmg cet assistant n'est-il pas uniquement destiné aux images de produits? Comment puis-je l'utiliser avec une image personnalisée qui n'est pas une image de produit mais une image téléchargée avec un module personnalisé dans le dossier / pub / media et n'a aucun rapport avec le produit?
kovinet
1
@kovinet - Cela fonctionne avec n'importe quelle image tant que l'image originale est contenue dans le dossier pub / media /. Passez simplement le chemin de l'image à $ image-> resize ('image / path / filename.ext');
Daniel Kratohvil
3

Je crains que vous n'ayez pas besoin de créer de nouvelles classes pour redimensionner vos images, car les assistants Magento l'ont déjà (voir \Magento\Catalog\Helper\Image::resize).

Donc, vous pouvez simplement faire:

$_imageHelper = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Catalog\Helper\Image');

echo $_imageHelper->init($product, 'small_image', ['type'=>'small_image'])->keepAspectRatio(true)->resize('65','65')->getUrl();

Vous pouvez également voir un exemple de cette utilisation sur \Magento\VisualMerchandiser\Block\Adminhtml\Category\Merchandiser\Tile::getImageUrl(Magento EE uniquement, je suppose)

Ricardo Martins
la source
Mais votre exemple ne fonctionnerait qu'avec des images de produits, non? La question concerne le module personnalisé avec le champ Image. Il n'y a donc pas de $productchemin d'accès au fichier image dans / media.
kovinet
Vous avez raison @kovinet. Je ne l'ai pas remarqué à ce moment-là. Cependant, ce fil m'a aidé avec les images de produits, et il semble que cela aide les autres. Mais merci pour ton commentaire. Dès que j'aurai du temps, je chercherai une meilleure réponse. ;)
Ricardo Martins
1

J'ai rencontré un problème où la resizeméthode ne recadrait pas l'image à mes dimensions, vous devez donc calculer les valeurs de recadrage de haut en bas ou de gauche à droite, en fonction de la taille de votre image d'origine. J'ai utilisé le code de @Rakesh et l'ai modifié pour qu'il vérifie si l'image d'origine est plus haute ou plus large et recadrée en conséquence:

public function resize($image, $width = null, $height = null)
{
    $mediaFolder = self::DIRECTORY;

    $path = $mediaFolder . 'cache';
    if ($width !== null) {
        $path .= '/' . $width . 'x';
        if ($height !== null) {
            $path .= $height ;
        }
    }

    $absolutePath = $this->_mediaDirectory->getAbsolutePath($mediaFolder) . $image;
    $imageResized = $this->_mediaDirectory->getAbsolutePath($path) . $image;

    if (!$this->_fileExists($path . $image) && $this->_fileExists($mediaFolder . $image)) {
        $imageFactory = $this->_imageFactory->create();
        $imageFactory->open($absolutePath);
        $imageFactory->constrainOnly(true);
        $imageFactory->keepAspectRatio(true);
        $imageFactory->keepFrame(false);

        $originalWidth = $imageFactory->getOriginalWidth();
        $originalHeight = $imageFactory->getOriginalHeight();

        $oldAspectRatio = $originalWidth / $originalHeight;
        $newAspectRatio = $width / $height;

        if ($oldAspectRatio > $newAspectRatio) {
            // original image is wider than the desired dimensions
            $imageFactory->resize(null, $height);
            $crop = ($imageFactory->getOriginalWidth() - $width) / 2;
            $imageFactory->crop(0, $crop, $crop, 0);
        } else {
            // it's taller...
            $imageFactory->resize($width, null);
            $crop = ($imageFactory->getOriginalHeight() - $height) / 2;
            $imageFactory->crop($crop, 0, 0, $crop);
        }

        $imageFactory->save($imageResized);

    }

    return $this->_storeManager
            ->getStore()
            ->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . $path . $image;
}
Zankar
la source
0

@Rakesh - J'ai fait la même chose mais ça ne marche pas pour moi il y a une erreur

Modèle de filtrage d'erreur Blockquote: Avertissement: getimagesize (/var/www/html/sitename/pub/media/onecategory/6/7/671471390.jpg): échec de l'ouverture du flux: aucun fichier ou répertoire de ce type dans / var / www / html /sitename/vendor/magento/framework/Image/Adapter/AbstractAdapter.php sur la ligne 304

pouvez-vous m'aider à ce sujet.

Je vous remercie.

Sarfaraj Sipai
la source
Trouvez-vous la solution? Parce que je suis dans ta situation maintenant. :(
fudu
veuillez vérifier l'autorisation de dossier ou de fichier.
Sarfaraj Sipai
n'a pas de dossier Aht_BannerSlider / images / slide_1.jpg dans C: /xampp/htdocs/magento/pub/media/Aht_BannerSlider/images/slide_1.jpg, et aussi je viens de donner l'autorisation pour le dossier pub.
fudu
Et ça ne marche toujours pas. :(
fudu
veuillez vérifier la dernière réponse sur cette page.
Sarfaraj Sipai