django-summernote icon indicating copy to clipboard operation
django-summernote copied to clipboard

S3 Links Expire for Images

Open gnall opened this issue 6 years ago • 7 comments

My S3 image links are expiring after one hour. This is because you store the URL to the backend within the textbox as the location it stores the file at with the Signature/Expiration that was given as a return from S3. This signature expires after 1 hour. I can make the Signature last 7 days at max, but then we're back to the same issue.

<img src="https://bucketname.s3.amazonaws.com/django-summernote/2020-03-04/5cb7c679-2143-434d-a6e2-5cec03225411.jpg?AWSAccessKeyId=AAAAAAAAAAAAAAAAAAAAAAA&amp;Signature=BvNIMcOJurphnCKZaarGQDDnHc8%3D&amp;Expires=1583302245" style="width: 25%;">

To solve this issue, couldn't you just reference the image location from the Attachments saved to the database?

https://bucketname.s3.amazonaws.com/django-summernote/2020-03-04/5cb7c679-2143-434d-a6e2-5cec03225411.jpg?AWSAccessKeyId=AAAAAAAAAAAAAAAAAAAAAAA&Signature=VowPCxFZ9ZjMbb7WdnhoMYk46Q8%3D&Expires=1583351249

gnall avatar Mar 04 '20 18:03 gnall

I had the same problem, I just wrote a thing to replace the db link and update it each time the summernote widget is rendered, but clearly it would be easier if there was a link with the image db

Kypaz avatar Jun 04 '20 11:06 Kypaz

Agreed this will be very helpful!

ed-lau avatar Jun 08 '20 01:06 ed-lau

This is the code to resolve the issue. Been using this for a couple years.

pip install beautifulsoup4

At the top of views.py

from bs4 import BeautifulSoup 
from urllib.parse import urlsplit

Within your view:

    if form.is_valid():
        instance = form.save(commit=False)
           
        #remove s3 query info in media files uploaded to summernote. This is because the file name is not being updated when served and thus, the link expires if we don't do this.

        soup = BeautifulSoup(instance.body, "html.parser")
        for img in soup.find_all('img'):
            img_url = img['src']
            new_url = urlsplit(img_url)._replace(query=None).geturl()
            img['src'] = new_url
        instance.body = str(soup) 

        instance.save()

I should mention that the field 'body' is the field with the summernote widget.

jasonhoward64 avatar Jun 25 '20 13:06 jasonhoward64

Awesome! Thanks - will try.

ed-lau avatar Jun 25 '20 17:06 ed-lau

Well, there is another simple way to do this. which is recommended by documentation.
just override django storage class like this.

from storages.backends.s3boto3 import S3Boto3Storage
class SummerNoteStorage(S3Boto3Storage):
    location = 'static'
    default_acl = 'public-read'
    querystring_auth=False

look at this option, it will do magic. querystring_auth=False
and then use this class in your settings file. like this.

SUMMERNOTE_CONFIG = {
    'attachment_absolute_uri': True,
    'attachment_storage_class': 'gradingly.storage_backends.SummerNoteStorage',
}

I hope this will be helpful.

aleemnazer avatar Apr 30 '22 17:04 aleemnazer

@aleemnazer it worked!

alexdeathway avatar Dec 04 '23 13:12 alexdeathway

Well, there is another simple way to do this. which is recommended by documentation.
just override django storage class like this.

from storages.backends.s3boto3 import S3Boto3Storage
class SummerNoteStorage(S3Boto3Storage):
    location = 'static'
    default_acl = 'public-read'
    querystring_auth=False

look at this option, it will do magic. querystring_auth=False
and then use this class in your settings file. like this.

SUMMERNOTE_CONFIG = {
    'attachment_absolute_uri': True,
    'attachment_storage_class': 'gradingly.storage_backends.SummerNoteStorage',
}

I hope this will be helpful.

Do you put this in settings.py?

csalsgiver007 avatar May 04 '24 19:05 csalsgiver007