如何使用Django Rest框架向AWS S3上传文件

526 阅读6分钟

如何使用Django Rest框架向AWS S3上传文件

文件上传和下载是网络上执行最多的一些操作。随着基于云的解决方案的兴起,公司正在从内部解决方案转移到云存储。几个原因是其更便宜的成本和便利性。

本文将演示如何使用Django Rest框架将用户生成的文件上传到Amazon S3。

前提条件

如果读者能够熟练使用Django和Django Rest框架,那么对跟随这篇文章会有帮助。

什么是AWS S3?

AWS S3是亚马逊网络服务简单存储服务(AWS S3)的首字母缩写。它是亚马逊为对象存储提供的一项基于云的服务。

对象存储是一种存储类型,其中项目被作为数据对象处理。与传统的文件系统层次结构中的文件存储方法相反。

在传统的文件系统中,存储的基本单位是一个 "文件"。在AWS S3中,存储的基本单位被称为 "桶"。

AWS控制台和AWS的可用SDK被用来访问桶。这些SDK有支持的流行语言,如Python和PHP。

使用AWS S3有几个优点。

这些优势包括。

  • 可扩展性
  • 高性能
  • 审计能力
  • 安全性
  • 成本效益高
  • 约99.999%的可用性(正常运行时间)。

AWS S3可以作为一个备份和灾难恢复工具,也可以用于数据分析。

在本指南中,我们将使用Django Rest框架上传用户生成的文件。

构建一个简单的Django Rest API应用程序

我们将创建一个名为Dropboxer的新Django项目。Dropboxer是一个简单的文件存储应用程序。

执行下面的命令来设置该项目。

pip install django
pip install djangorestframework
django-admin startproject dropboxer
cd dropboxer
python manage.py startapp uploader

文件夹结构看起来像下面的结构。

- dropboxer
- uploader
- manage.py

在settings.py中添加新的应用程序到INSTALLED_APPS

# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
# 3rd party apps
    'rest_framework',
    # local apps
    'uploader',  # new
]
…
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

将下面的代码片段添加到dropboxer 项目目录下的urls.py 文件中。

from django.conf import settings  # new
from django.conf.urls.static import static  # new
from django.contrib import admin
from django.urls import path
urlpatterns = [
    path('admin/', admin.site.urls),
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

uploader 应用程序中创建serializers.pyurls.py 文件。

models.py 文件中,我们创建一个简单的模型,代表一个单一的文件。

from django.db import models
 
class DropBox(models.Model):
    title = models.CharField(max_length=30)
    document = models.FileField(max_length=30)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
 
    class Meta:
        verbose_name_plural = 'Drop Boxes'

serializers.py 文件中添加下面的代码片断。

from rest_framework import serializers
from .models import DropBox
class DropBoxSerializer(serializers.ModelSerializer):
 
    class Meta:
        model = DropBox
        fields = '__all__'

uploader/views.py

from rest_framework import viewsets, parsers
from .models import DropBox
from .serializers import DropBoxSerializer
class DropBoxViewset(viewsets.ModelViewSet):
 
    queryset = DropBox.objects.all()
    serializer_class = DropBoxSerializer
    parser_classes = [parsers.MultiPartParser, parsers.FormParser]
    http_method_names = ['get', 'post', 'patch', 'delete']

uploader/urls.py

from rest_framework.routers import SimpleRouter
from .views import DropBoxViewset
router = SimpleRouter()
router.register('accounts', DropBoxViewset)
urlpatterns = router.urls

uploader/admin 中。

from django.contrib import admin
from .models import DropBox
admin.site.register(DropBox)

dropboxer/urls.py 中。

...
from django.urls import path, include  # new
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('rest_framework.urls')),  # new
    path('', include('uploader.urls')),  # new
]

为了从我们上面创建的模型在数据库中创建一个表,执行下面的命令。

python manage.py makemigrations
python manage.py migrate

通过执行下面的命令启动开发服务器。

python manage.py runserver

在浏览器上导航到账户。我们在媒体文件夹中找到上传的样本文件。

这个样本文件是我们通过浏览器上的API上传时创建的,如下图所示。

media_folder_included_vs_code

sample_upload_via_api

将AWS S3整合到Django API应用程序中

我们有一个工作的应用程序API端点。你需要一个AWS账户来启用AWS S3与你的Django应用程序的集成。

如果你还没有账户,请注册,如果你有一个现有的AWS账户,请登录

搜索S3

search_for_s3

点击 "创建桶"按钮。

click_create_bucket

为你的S3桶提供一个全球通用的唯一名称。

globally_named_bucket

在发现一个不存在的名字之前,命名一个AWS S3桶可能需要一些尝试和错误。

保持默认选项,点击创建桶

finish_bucket_creation

你将被重定向到AWS S3控制台,现在显示新创建的桶。

successful_create_bucket

我们已经成功创建了一个AWS S3桶。回顾一下,在桶的创建过程中,公众对S3桶的访问被阻止了。

为了从我们的应用程序访问创建的桶,我们将需要使用AWS IAM获得访问权。AWS IAM是身份和访问管理的首字母缩写。

它用于提供对AWS资源的权利和特权的访问。目前,我们只能通过控制台访问S3桶。

AWS允许通过用户和角色来访问其资源,如AWS S3。

使用AWS搜索栏搜索IAM。

search_iam

在IAM侧面菜单上点击用户

click_user

在IAM用户仪表板上点击添加用户

add_user

提供一个用户名并勾选程序性访问框。

assign_username_and_access_type

设置权限中,选择 "直接附加现有策略"并勾选AWSS3FullAcess框。

set_permissions

在创建用户之前,点击一下并审查你的选择。

user_summary

创建成功后,它生成了一个AWS访问和秘密密钥。

access_key_generated

在完成之前存储AWS秘钥,因为秘钥不会再显示。

一旦完成,我们可以在IAM用户仪表板上查看新创建的AWS用户。

new_user

在这篇文章中,我们将使用Django-storages来连接AWS S3桶。

Django-storages是一个为Django框架定制的存储后端集合。我们将使用Django-storages包中的AWS S3集成。

通过pip将django-storages安装到Django应用程序中。

pip install django-storages

在settings.py中加入下面的代码片段。

...
AWS_ACCESS_KEY_ID = <YOUR AWS ACCESS KEY>
AWS_SECRET_ACCESS_KEY = <YOUR AWS SECRET KEY>
AWS_STORAGE_BUCKET_NAME = <YOUR AWS S3 BUCKET NAME>
AWS_S3_SIGNATURE_VERSION = 's3v4'
AWS_S3_REGION_NAME = <YOUR AWS S3 BUCKET LOCATION>
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
AWS_S3_VERIFY = True
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' 

AWS_ACCESS_KEY_ID:是IAM用户的关键标识符。它以 "AK****"开头。

AWS_SECRET_ACCESS_KEY: 是生成的40个字母数字字符。

AWS_S3_REGION_NAME: 指的是S3控制台仪表板中的AWS区域。例如:us-east-1,eu-west-2

AWS_S3_SIGNATURE_VERSION: 是用于生成预签名URL的签名版本。AWS S3桶需要该签名来授予访问权。

AWS_S3_FILE_OVERWRITE:当设置为True ,AWS S3会覆盖一个具有相同名称和格式的文件。如果设置为False ,AWS将独特的字符串附加到新上传的文件名。它不会覆盖现有的文件。

通过执行下面的命令重新启动开发服务器。

python manage.py runserver

在浏览器上,导航到localhost并重新尝试上传一个样本文件。

aws_successful_upload

点击document 领域中的链接。注意链接现在有 "s3.amazon**"。你将能够访问该文件。这里,上传的文件标题为 "Big O Cheatsheet"。

remote_file

总结

在这篇文章中,我们创建了一个AWS S3桶,并给IAM用户分配了对AWS S3桶的完全访问权。我们从我们的Django Rest API应用程序中使用访问密钥和AWS秘密密钥将文件上传到AWS S3桶中。