简体   繁体   中英

How to auto-upload an image from django app to aws s3

When a user creates or registers for a new account on my website, an image is created(generated) and is supposed to be uploaded to the s3 bucket. The image is successfully created(verified by running the ls command on the server in the media directory) but it's not getting uploaded to s3. However, when I try uploading an image for a user account from the admin panel, changes are correctly reflected in s3 (ie newly uploaded image from admin panel is shown in s3 bucket's directory, but this is not feasible as the users cannot be given admin panel access). I aim to auto-upload the generated image to the s3 bucket when a new account is created.
Here's some related code.

def signup(request):

    if request.method == "POST":
        base_form = UserForm(data=request.POST)
        addnl_form = AddnlForm(data=request.POST)

        if base_form.is_valid() and addnl_form.is_valid():

            usrnm = base_form.cleaned_data['username']
           
            if UserModel.objects.filter(user__username=usrnm).count()==0:
                user = base_form.save()
            user.set_password(user.password)
            user.save()

            #print(img)

            addnl = addnl_form.save(commit=False )
            addnl.user = user
            
            
            
            img = qr.make_image()  #create a qr code image, full code not included.
            img.save('media/qrcodes/%s.png'%usrnm)
           
                
            addnl.qr_gen = 'qrcodes/%s.png'%usrnm
            addnl.save()

        
        else:
            messages.error(request,base_form.errors,addnl_form.errors)
    else:
        base_form = UserForm()
        addnl_form = AddnlForm()
    
    return render(request,'app/signup.html',{'base_form':base_form,'addnl_form':addnl_form} )

class UserModel(models.Model):
   .
   .
   .
   qr_gen = models.ImageField(upload_to='qrcodes',default=None,null=True,blank=True)

DEFAULT_FILE_STORAGE = 'project.storage_backend.MediaStorage'

from storages.backends.s3boto3 import S3Boto3Storage


class MediaStorage(S3Boto3Storage):
    location = 'media'
    default_acl = 'public-read'
    file_overwrite = False


Instead of auto-generating, an image and uploading it to s3, if I upload any image in the registration form, even in that case it's successfully uploading to s3, the only case where it fails is when I need to auto-upload without user intervention.
Please help me solve this problem. Thank you.

I would recommend taking a look at django-storages which automates all of this so you should only worry about the form and the view instead of anything else. In there you will find help on how to deal with images easily.

Instead of globally setting media storage settng, set it on the field

class UserModel(models.Model):
    ...
    qr_gen = models.ImageField(upload_to='qrcodes',storage=MediaStorage())

Auto uploading an image directly to s3 requires one to directly communicate with S3's backend API. Plainly using django-storages or tweaking DEFAULT_FILE_STORAGE path isn't just enough as it only helps to point user-uploaded files to the specified s3 bucket/path. This problem can be tackled using the boto3 library's upload_file method.

import boto3
s3 = boto3.resource('s3')
s3.Bucket('mybucket').upload_file('/tmp/hello.txt', 'hello.txt')

Params:

-- The path to the file to upload. -- 要上传的文件的路径。
-- The name of the key to upload to. -- 要上传到的密钥的名称。
-- Extra arguments that may be passed to the client operation. -- 可以传递给客户端操作的额外 arguments。
-- A method which takes a number of bytes transferred to be periodically called during the upload. ——一种在上传期间定期调用传输的字节数的方法。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM