为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 django 应用程序在 AWS S3 中上传文件?

如何使用 django 应用程序在 AWS S3 中上传文件?

喵喔喔 2023-12-26 16:16:02
我在上传用户个人资料图片时遇到问题。现在,当我在 Django 管理中创建用户并从管理仪表板上传文件时,它可以正常工作,没有错误。它按照应有的方式进入我的 AWS S3 存储桶,但这显然是不可行的,我一直在寻找解决方案 3 到 4 天,但没有成功或没有任何令人满意的结果。我显然不会向用户提供仪表板访问权限。使用的数据库是MongoDB,数据库引擎是djongo。这是我的设置.pyINSTALLED_APPS = [    'profileupload',    's3direct',    'storages',    'django.contrib.admin',    'django.contrib.auth',    'django.contrib.contenttypes',    'django.contrib.sessions',    'django.contrib.messages',    'django.contrib.staticfiles',    'django.contrib.humanize',]STATIC_URL = '/static/'MEDIA_ROOT = os.path.join(BASE_DIR, 'media')MEDIA_URL = '/media/'AWS_SECRET_ACCESS_KEY = 'MY_SPECIAL_KEY'AWS_ACCESS_KEY_ID = 'MY_SPECIAL_KEY_NAME'AWS_STORAGE_BUCKET_NAME = 'S3_BUCKET'AWS_S3_FILE_OVERWRITE = FalseAWS_DEFAULT_ACL = NoneDEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'我的网址.pyfrom django.urls import path, includefrom .views import signup_formurlpatterns = [    path('signup', signup_form, name='signup'),]我的模型.pyclass profile(models.Model):    profile_id = models.AutoField(primary_key=True,unique=True)    profile_username = models.CharField(max_length=100,unique=True)    profile_name = models.CharField(max_length=150)    profile_email = models.EmailField(max_length=200)    profile_create_time = models.DateField(auto_now_add=True)    profile_dob = models.DateField()    profile_password = models.CharField(max_length=50, null=True)    profile_picture = models.ImageField(default='default.jpg', upload_to='profile_pics')    def __str__(self):        return str(self.profile_username)另外,我想更改上传文件的名称,由 Django admin 上传的文件采用文件名,但是当我将这个应用程序公开给公众时,文件名必须正确,以避免被覆盖或具有同一个文件多次
查看完整描述

2 回答

?
烙印99

TA贡献1829条经验 获得超13个赞

正如已经提到的,一种方法是直接使用该boto3库。

另一种方法是使用(也在后台使用)save的功能。django-storagesboto3

如果只有1个桶:

settings.py

...


INSTALLED_APPS = [

    ...

    "storages",

    ...

]


...



DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'


AWS_ACCESS_KEY_ID = 'my-access-key-id'

AWS_SECRET_ACCESS_KEY = 'my-secret-access-key'

# Depending on the AWS account used, you might also need to declare AWS_SESSION_TOKEN as an environment variable


AWS_STORAGE_BUCKET_NAME = 'my-bucket'


...

views.py


from io import BytesIO


from django.core.files.storage import default_storage

from rest_framework.decorators import api_view

from rest_framework.response import Response



@api_view(('GET',))

def save_file(request):

    file_name = "toguro.txt"

    file_content = b"I have my full 100% power now!"

    file_content_io = BytesIO(file_content)


    default_storage.save(file_name, file_content_io)


    return Response({"message": "File successfully saved"})

如果有很多桶:

settings.py


...


INSTALLED_APPS = [

    ...

    "storages",

    ...

]


...


AWS_ACCESS_KEY_ID = 'my-access-key-id'

AWS_SECRET_ACCESS_KEY = 'my-secret-access-key'

# Depending on the AWS account used, you might also need to declare AWS_SESSION_TOKEN as an environment variable


...

views.py


from io import BytesIO


from rest_framework.decorators import api_view

from rest_framework.response import Response

from storages.backends.s3boto3 import S3Boto3Storage



# For a clear separation-of-concern, you should consider placing this code to its appropriate place

class MyStorage1(S3Boto3Storage):

    bucket_name = 'my-bucket-1'



class MyStorage2(S3Boto3Storage):

    bucket_name = 'my-bucket-2'



@api_view(('GET',))

def save_file(request):

    file_name_1 = "toguro.txt"

    file_name_2 = "sensui.txt"

    file_content_1 = b"I have my full 100% power now!"

    file_content_2 = b"I will release the S-Class demons!"

    file_content_io_1 = BytesIO(file_content_1)

    file_content_io_2 = BytesIO(file_content_2)


    storage1 = MyStorage1()

    storage2 = MyStorage2()

    storage1.save(file_name_1, file_content_io_1)

    storage2.save(file_name_2, file_content_io_2)


    return Response({"message": "File successfully saved"})


查看完整回答
反对 回复 2023-12-26
?
BIG阳

TA贡献1859条经验 获得超6个赞

好的,所以我知道了应用错误的访问键并在views.py 中接受错误的输入


首先在views.py中获取正确的输入


pr.profile_picture = request.POST.get('profile_picture')

除了使用上述内容之外,以下内容会有所帮助:


pr.profile_picture  = request.FILES["profile_picture"]

另外,当我将上面的内容与单个引号一起使用时,它将不起作用,所以请记住这一点。


将文件上传到S3


现在将有一些其他方法来执行此操作,但同时更改文件名。


我专门制作了另一个文件来处理图像并更改文件名。


import boto3


session = boto3.Session(

    aws_access_key_id= 'secret sauce',

    aws_secret_access_key = 'secret sauce'

)


class image():

    def UploadImage(name,image):

        filename = name+'_picture.jpg'

        imagedata = image

        s3 = boto3.resource('s3')

        try:

            object = s3.Object('bucket sauce', filename)

            object.put(ACL='public-read',Body=imagedata,Key=filename)

            return True

        except Exception as e:

            return e

上面的方法在views.py中调用


ret = image.UploadImage(pr.profile_username,pr.profile_picture)

将其放在 try 块中以避免错误。


查看完整回答
反对 回复 2023-12-26
  • 2 回答
  • 0 关注
  • 48 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信