Django Rest FrameworkでAmazon S3のファイルをダウンロードするAPIを作成する


前提条件

  • AWS S3の読み取り権限を持ったユーザを用意すること
  • AWS コマンドラインインターフェイスを使って、上記ユーザでログイン済みであること
    また、本記事で扱う言語・ライブラリのバージョンを以下に示します。
python-3.9.5
Django==3.2.4
djangorestframework==3.12.4
boto3==1.17.91

ファイルの準備

AWSコンソールからS3に入って適当なファイルをバケットに配置します。
今回はtest-qiitaバケットを作成し、test.txtというテキストファイルをアップロードしました。

本記事ではDjango REST Frameworkを用いて、このtest.txtをダウンロードするAPIを作成することを目指します。

APIの準備

先に最低限のAPIをエンドポイントを用意しておきましょう。
作成するAPIは/api/fileというURLにGETリクエストをする仕様とします。

まずはfile_download_testという名前でDjangoプロジェクトを作成し、
apiという名前でdjangoアプリケーションを作成します。

$ django-admin startproject file_download_test
$ django-admin startapp api

次にapi/views.pyを編集します。

api/views.py
from django.http import HttpResponse
from rest_framework.views import APIView


class FileView(APIView):

    def get(self, request):
        response = HttpResponse('ok')
        return response

そしてurls.pyでURLとFileViewを対応させます。

file_download_test/urls.py
from django.contrib import admin
from django.urls import path

from api import views # 追加

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/file', views.FileView.as_view()), # 追加
]

以上です。
APIを試してみましょう。

$ python .\manage.py runserver

コマンドラインから実行しサーバを立ち上げ、ブラウザからlocalhost:8000/api/fileにアクセスします。


このようにokが返ってくれば成功です。

S3からファイル取得

いよいよ本題に入ります。先ほど作成した/api/fileAPIをS3のファイルを返すように修正します。
まずは、PythonでAWSを利用するのによく使われるboto3というライブラリをインストールします。

$ pip install boto3

boto3を使うにあたっての注意点

boto3を使ってAWSに接続するためには認証情報が必要です。AWS コマンドラインインターフェイスでログインすると、~/.aws/credentials が自動で作成され、そこからその中身は以下のように認証に必要な情報が書き込まれます。

credentials
aws_access_key_id = ******************
aws_secret_access_key = ************************

boto3はこのファイルの情報を使ってAWSと接続します。
※Dockerコンテナの場合等~/.aws/credentialsが見えない場合は、環境変数に以下の名前で値を設定してください。

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

API修正

次にviews.pyを以下のように修正します。

api/views.py
import boto3
from django.http import HttpResponse
from rest_framework.views import APIView


class FileView(APIView):

    def get(self, request):
        s3 = boto3.resource('s3')
        BUCKET_NAME = 'test-qiita'
        FILE_NAME = 'test.txt'
        object = s3.Object(BUCKET_NAME, FILE_NAME).get()
        response = HttpResponse(object['Body'].iter_chunks(), content_type=object['ContentType'])
        response['Content-Disposition'] = f'attachment; filename="{FILE_NAME}"'

        return response

再度ブラウザからlocalhost:8000/api/fileにアクセスしましょう。


無事にファイルがダウンロードできました!

今回作成したファイルはこちらで確認いただけます。