SmileyChris / easy-thumbnails

Easy thumbnails for Django
http://easy-thumbnails.readthedocs.org/
BSD 3-Clause "New" or "Revised" License
1.37k stars 312 forks source link

SVG File.width - This backend doesn't support absolute paths. #619

Open DmytroLitvinov opened 11 months ago

DmytroLitvinov commented 11 months ago

We are using AWS S3 as a remote storage. And we found an issue when we use SVG file with django-filer library and then we tried to use thumbnail template tags which is used next code:

  <picture class="hero-content__picture">
    {% thumbnail img 414x224 crop quality=79 as thumb %}
    {% thumbnail img 828x448 crop quality=79 as thumb2x %}
    {% thumbnail img 1242x672 crop quality=79 as thumb3x %}
    {% thumbnail img 800x433 crop quality=79 as thumb_medium %}
    {% thumbnail img 1600x866 crop quality=79 as thumb_medium2x %}
    {% thumbnail img 1440x778 crop quality=79 as thumb_large %}
    {% thumbnail img 2880x1556 crop quality=79 as thumb_large2x %}
    <source srcset="{{ thumb.url }} 1x, {{ thumb2x.url }} 2x, {{ thumb3x.url }} 3x"
            media="(max-width: 414px)" width="{{ thumb.width }}" height="{{ thumb.height }}">
    <source srcset="{{ thumb_medium.url }} 1x, {{ thumb_medium2x.url }} 2x"
            media="(max-width: 800px)" width="{{ thumb_medium.width }}" height="{{ thumb_medium.height }}">
    <img src="{{ thumb_large.url }}" width="{{ thumb_large.width }}" height="{{ thumb_large.height }}" alt="{{ alt }}"
         srcset="{{ thumb_large.url }} 1x, {{ thumb_large2x.url }} 2x">
  </picture>

The issue itself with thumb.width which is under the hood is failed with next traceback:

image

The issue is in 121th line. After checking with blame functionally, I see file.path was adapted because of that possible case - more information in that commit https://github.com/SmileyChris/easy-thumbnails/commit/8a06fc7db58a4b796673c20876b124be554aaabc. We see that file.path was omitted with file.file.name.

Not sure if it will resolve, but in that line of code - https://github.com/SmileyChris/easy-thumbnails/blob/77265b715a1f623b3c42abc8d044535d880971bd/easy_thumbnails/files.py#L121 we should pass file.file instead of file.path.

Currently, my colleague is working on monkey-patch to verify it so I will update after my ticket. UPD: colleague confirmed that monkey-patch works

@jrief , I would appreciate your feedback on the issue since you are who was in developing it. Thank you🙏

jrief commented 11 months ago

Since I have no access to S3, I can't test this. Would you be so kind and share the patch of your colleague as a PR.

DmytroLitvinov commented 11 months ago

Sure,

Here is a patch we applied and it works for us:

def database_get_image_dimensions(file, close=False, dimensions=None):  # noqa: VNE002
    """
    Change svg file dimensions, because - https://github.com/SmileyChris/easy-thumbnails/issues/619
    """
    storage_hash = utils.get_storage_hash(file.storage)
    dimensions = None
    dimensions_cache = None
    try:
        thumbnail = models.Thumbnail.objects.select_related('dimensions').get(storage_hash=storage_hash, name=file.name)
    except models.Thumbnail.DoesNotExist:
        thumbnail = None
    else:
        try:
            dimensions_cache = thumbnail.dimensions
        except models.ThumbnailDimensions.DoesNotExist:
            dimensions_cache = None
        if dimensions_cache:
            return dimensions_cache.width, dimensions_cache.height
    if os.path.splitext(file.file.name)[1] == '.svg':
        from easy_thumbnails.VIL.Image import load

        dimensions = load(file.file).size
    else:
        dimensions = get_image_dimensions(file, close=close)
    if settings.THUMBNAIL_CACHE_DIMENSIONS and thumbnail:
        models.ThumbnailDimensions.objects.get_or_create(
            thumbnail=thumbnail, defaults={'width': dimensions[0], 'height': dimensions[1]}
        )
    return dimensions

easy_thumbnails_files.database_get_image_dimensions = database_get_image_dimensions