Flask, DynamoDB, Lambda, S3, Zappaを使ってPDFアップロード・表示アプリを作成する #
はじめに
このチュートリアルでは、Flask, DynamoDB, Lambda, S3, Zappaを使用して、PDFをアップロードし、S3に保存し、表示するアプリケーションを作成します。
1. 環境の準備 #
まず、新しいディレクトリを作成し、仮想環境を設定します。
$ mkdir pdf-upload-app
$ cd pdf-upload-app
$ python3 -m venv venv
$ source venv/bin/activate
次に、必要なパッケージをインストールします。
$ pip install flask boto3 zappa requests
requestsライブラリを使用して、プリサインされたURLからPDFデータを取得し、そのデータをレスポンスとして返します。
プロジェクトの構成 #
プロジェクトディレクトリを作成し、次のような構成でファイルを作成します。
pdf-upload-app/
├── app.py
├── templates/
│ ├── index.html
│ └── upload.html
└── zappa_settings.json
S3バケットの設定 #
AWSコンソールでS3バケットを作成し、バケット名をメモしておきます。
app.pyとzappa用に二つ必要です。
DynamoDBテーブルの設定 #
AWSコンソールでDynamoDBテーブルを作成し、テーブル名とパーティションキーをメモしておきます。
PDFのアップロードと表示機能の実装 #
app.pyにPDFのアップロードと表示機能を実装します。
[app.py]
from flask import Flask, render_template, request, redirect, url_for, Response
import boto3
import os
from werkzeug.utils import secure_filename
from uuid import uuid4
from botocore.exceptions import NoCredentialsError
import requests
app = Flask(__name__)
# S3およびDynamoDBの設定
S3_BUCKET = 'your-s3-bucket-name'
DYNAMO_TABLE = 'your-dynamodb-table-name'
s3 = boto3.client('s3')
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(DYNAMO_TABLE)
ALLOWED_EXTENSIONS = {'pdf'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/')
def index():
response = table.scan()
pdfs = response['Items']
return render_template('index.html', pdfs=pdfs)
@app.route('/upload', methods=['GET', 'POST'])
def upload():
if request.method == 'POST':
if 'file' not in request.files:
return redirect(request.url)
file = request.files['file']
if file.filename == '':
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file_extension = filename.split('.')[-1]
unique_filename = f"{uuid4()}.{file_extension}"
pdf_id = str(uuid4())
try:
s3.upload_fileobj(file, S3_BUCKET, unique_filename)
table.put_item(
Item={
'id': pdf_id,
'file_name': unique_filename,
}
)
return redirect(url_for('view', pdf_id=pdf_id))
except NoCredentialsError:
return "Error: S3へのアクセス権がありません。"
return render_template('upload.html')
@app.route('/view/<string:pdf_id>')
def view(pdf_id):
try:
response = table.get_item(Key={'id': pdf_id})
file_name = response['Item']['file_name']
presigned_url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': S3_BUCKET, 'Key': file_name},
ExpiresIn=3600
)
pdf_data = requests.get(presigned_url).content
return Response(pdf_data, content_type='application/pdf')
except KeyError:
return "Error: PDFが見つかりません。"
if __name__ == '__main__':
app.run()
このコードでは、index()関数でアプリケーションのホーム画面、upload()関数でPDFアップロード機能、view()関数でアップロードされたPDFの表示機能をそれぞれ実装しています。また、S3およびDynamoDBの設定も行っています。 PDFデータをResponseオブジェクトに渡し、content_typeをapplication/pdfとして返します。これで、ブラウザでPDFファイルが表示されるようになります。
[templates/index.html]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"content="width=device-width,initial-scale=1.0">
<title>Image App</title>
</head>
<body>
<h1>Welcome to the Image App</h1>
<p><a href="{{ url_for('upload') }}">Uploadan image</a></p>
<h2>Uploaded Images</h2>
{% for image in images %}
<p>
<a href="{{ url_for('view',image_id=image.id) }}">Image: {{image.file_name }}</a>
</p>
{% endfor %}
</body>
</html>
[templates/update.html]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload Image</title>
</head>
<body>
<h1>Upload an Image</h1>
<form action="{{ url_for('upload') }}" method="post" enctype="multipart/form-data">
<p><input type="file" name="file"></p>
<p><input type="submit" value="Upload"></p>
</form>
<p><a href="{{ url_for('index') }}">Back to Home</a></p>
</body>
</html>
Zappaを使ってLambdaにデプロイ #
{
"production": {
"app_function": "app.app",
"aws_region": "ap-northeast-1",
"s3_bucket": "your-zappa-deploy-bucket",
"project_name": "image-app",
"runtime": "python3.8",
"timeout_seconds": 30
}
}
Zappaを使ってデプロイします。
$ zappa deploy production
ウェブアプリケーションのテスト #
デプロイが完了したら、表示されたURLにアクセスしてウェブアプリケーションをテストします。PDFをアップロードし、正常に表示されるか確認します。
以上で、Flask, DynamoDB, Lambda, S3, Zappaを使用してPDFを投稿・保存・表示するウェブアプリケーションの作成が完了しました。