Sylius / ShopApiPlugin

Shop API for Sylius.
https://sylius.com
130 stars 89 forks source link

product-latest Unable to open image svg #695

Closed FDiskas closed 3 years ago

FDiskas commented 3 years ago

If I request the endpoint http://localhost/shop-api/product-latest/ I got the flowing error

{
    "code": 500,
    "message": "Unable to open image /srv/sylius/public/media/image/43/97/e0fe3450b896642e5efb574872a3.svg"
}

Steps to reproduce:

  1. Clone https://github.com/Sylius/Sylius-Standard
  2. docker-compose up
  3. install sylius with sample data
  4. install shopapiplugin
  5. request the endpoint http://localhost/shop-api/product-latest/

As far as I understand svg is with embeded png

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   version="1.1"
   id="svg10"
   width="1200"
   height="1200"
   viewBox="0 0 1200 1200"
   sodipodi:docname="jeans.svg"
   inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
  <metadata
     id="metadata16">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title></dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <defs
     id="defs14" />
  <sodipodi:namedview
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1"
     objecttolerance="10"
     gridtolerance="10"
     guidetolerance="10"
     inkscape:pageopacity="0"
     inkscape:pageshadow="2"
     inkscape:window-width="743"
     inkscape:window-height="480"
     id="namedview12"
     showgrid="false"
     inkscape:zoom="0.17280891"
     inkscape:cx="600"
     inkscape:cy="800"
     inkscape:window-x="2446"
     inkscape:window-y="209"
     inkscape:window-maximized="0"
     inkscape:current-layer="g18" />
  <g
     inkscape:groupmode="layer"
     inkscape:label="Image"
     id="g18">
    <image
       width="1200"
       height="1600"
       preserveAspectRatio="none"
       xlink:href="data:imag
...

Sample image

e0fe3450b896642e5efb574872a3.zip

FDiskas commented 3 years ago

After re uploading product image file as simple png it fixes the issue.

mamazu commented 3 years ago

Thanks for finding this restriction. This problem is due to the fact that the liip bundle (which is used to generate the product images) can not handle svg images.

robin-aeist commented 3 years ago

After re uploading product image file as simple png it fixes the issue.

Hello, I have the same problem (exact same) but all of my image are jpg. How could I fix that ?

EmilMassey commented 3 years ago

@robin-aeist Your problem is a little bit different as jpg files should be properly handled by liip bundle.

Jeroen-G commented 3 years ago

This does not work when the SVG is stored in cloud storage (e.g. S3). In case someone else encounters this issue, this is how we resolved it:

  1. Write a compiler pass to revert the change of filter extension
    final class LiipImageFiltersPass implements CompilerPassInterface
    {
    public function process(ContainerBuilder $container): void
    {
        $useDefaultFilterExtension = new Definition(FilterExtension::class);
        $useDefaultFilterExtension->setArguments([new Reference('liip_imagine.cache.manager')]);
        $useDefaultFilterExtension->addTag('twig.extension');
        $container->setDefinition('liip_imagine.templating.filter_extension', $useDefaultFilterExtension);
    }
    }
  2. Register this in kernel.php
    public function build(ContainerBuilder $container): void
    {
     $container->addCompilerPass(new LiipImageFiltersPass());
    }
  3. We extended the Liip filter manager to support the right SVG mime type
    
    use Liip\ImagineBundle\Binary\BinaryInterface;
    use Liip\ImagineBundle\Imagine\Filter\FilterManager as BundleFilterManager;
    use Liip\ImagineBundle\Model\Binary;

final class FilterManager extends BundleFilterManager { public function apply(BinaryInterface $binary, array $config): BinaryInterface { $config += [ 'quality' => 100, 'animated' => false, ];

    if ($binary->getFormat() === 'svg') {
        $svgBinary = new Binary($binary->getContent(), 'image/svg+xml', $binary->getFormat());

        return $this->applyPostProcessors($svgBinary, $config);
    }

    return $this->applyPostProcessors($this->applyFilters($binary, $config), $config);
}

}

4. And registered this in services.yaml
```yaml
    liip_imagine.filter.manager:
      class: App\Service\Liip\FilterManager
      arguments:
        - "@liip_imagine.filter.configuration"
        - "@liip_imagine"
        - "@liip_imagine.binary.mime_type_guesser"

And voila, SVGs are supported no matter the place where they are stored.