Wenn beim Teilen einer großen Datei die E-Mail mehr als 8 MB überschreitet, wird sie blockiert, da es sich um einen Mailserver handelt. Selbst wenn es nicht blockiert ist, kann das Senden einer großen Datei per E-Mail ziemlich ärgerlich sein, z. B. das Laden des Servers. Ich möchte den Speicherdienst nutzen, aber wenn es sich um einen Giga-Dateiflug handelt, ärgere ich mich wahrscheinlich über die Sicherheitsvereinbarung (ich habe sie in der Vergangenheit häufig verwendet), und Google Drive ist besorgt über die Freigabe ohne Google-Konto (Zugriff, wenn ich die URL nicht kenne). Obwohl dies nicht möglich ist, ist es für alle schwierig, darauf zuzugreifen.
Ich möchte nur eine URL, über die ich vorübergehend eine ID anwenden und eine große Datei freigeben und freigeben kann ... (Löschen Sie sie nach dem Ende oder machen Sie sie nach Ablauf des Zeitlimits privat.)
Daher habe ich kürzlich SAA von aws erhalten und mich herausgefordert, einen Mechanismus zum einfachen Teilen von Dateien mit aws als Überprüfung zu erstellen. Dies war der Grund für diesen Artikel.
Persönlich wollte ich den Server nicht ein- oder ausschalten oder überwachen, also fragte ich mich, ob ich ihn ohne Server erstellen könnte.
Die Größe der Datei, die Sie freigeben möchten, beträgt übrigens etwa 100 MB.
API Gateway
So veröffentlichen Sie Lambda und wenden die Standardauthentifizierung auf die veröffentlichte URL an. Nach der Überprüfung verfügt API Gateway über eine Methode namens "API Gateway Lambda Authorizer", mit der Sie sich mit einem Zugriffsschlüssel authentifizieren und Lambda vorbereiten und den API-Zugriff damit steuern können.
Lambda
Bereiten Sie eine Lambda-Funktion vor, die die Basisauthentifizierung für die Verwendung des "API Gateway Lambda Authorizer" anwendet, und bereiten Sie zwei Seiten für das Herunterladen der Zip-Datei nach der Basisauthentifizierung mit der Lambda-Funktion vor.
Eine besteht darin, HTML anzuzeigen und sie zu bitten, die herunterzuladende Datei auszuwählen. Zuerst dachte ich, es wäre in Ordnung, es herunterzuladen, wenn ich auf die URL trete, aber was ist, wenn es mehrere Dateien gibt? Also habe ich beschlossen, eine HTML-Seite vorzubereiten. (Wenn ich jetzt darüber nachdenke, bin ich froh, dass ich den Abfrageparameter verwendet habe. Ja ... → Ich dachte, aber es hat nicht funktioniert. Siehe unten.)
Die andere ist eine Lambda-Funktion, die Dateien aus S3 herunterlädt und eine Zip-Datei (binär) zurückgibt.
S3
Verwenden Sie es als Speicherort für Zip-Dateien, die Sie herunterladen möchten, und als Speicherort für HTML-Vorlagen.
TODO: Erstellen Sie ein Diagramm und fügen Sie es ein
Lambda
Funktionsname: download ___ auth
Lambda für die Basisauthentifizierung
import json
import os
import base64
def lambda_handler(event, context):
policy = {
'principalId': 'user',
'policyDocument': {
'Version': '2012-10-17',
'Statement': [
{
'Action': 'execute-api:Invoke',
'Effect': 'Deny',
'Resource': event['methodArn']
}
]
}
}
if not basic_auth(event):
print('Auth Error!!!')
return policy
policy['policyDocument']['Statement'][0]['Effect'] = 'Allow'
return policy
def basic_auth(event):
if 'headers' in event.keys() and 'authorization' in event['headers'].keys():
auth_header = event['headers']['authorization']
#Informationen aus Lambda-Umgebungsvariablen abrufen.
user = os.environ['USER']
password = os.environ['PASSWORD']
print(os.environ)
_b64 = base64.b64encode('{}:{}'.format(user, password).encode('utf-8'))
auth_str = 'Basic {}'.format(_b64.decode('utf-8'))
return auth_header == auth_str
raise Exception('Auth Error!!!')
Funktionsname: download ___ index
Ein Lambda, das herunterladbare Dateien in HTML anzeigt. Die HTML-Vorlage wird von S3 bezogen. Die Template-Engine ist Jinja.
from jinja2 import Template
import boto3
from botocore.exceptions import ClientError
import os
import logging
logger = logging.getLogger()
S3 = boto3.resource('s3')
TEMPLATE_AWS_S3_BUCKET_NAME = 'hogehoge-downloader'
BUCKET = S3.Bucket(TEMPLATE_AWS_S3_BUCKET_NAME)
def get_object(bucket, object_name):
"""Retrieve an object from an Amazon S3 bucket
:param bucket_name: string
:param object_name: string
:return: botocore.response.StreamingBody object. If error, return None.
"""
try:
response = bucket.Object(object_name).get()
except ClientError as e:
# AllAccessDisabled error == bucket or object not found
logging.error(e)
return None
# Return an open StreamingBody object
return response['Body'].read()
def main():
index_html = get_object(BUCKET,
os.path.join('template', 'index.html')) \
.decode('utf8')
li_html = get_object(BUCKET,
os.path.join('template', 'file_li.html')) \
.decode('utf8')
index_t = Template(index_html)
insert_list = []
objs = BUCKET.meta.client.list_objects_v2(Bucket=BUCKET.name,
Prefix='files')
for obj in objs.get('Contents'):
k = obj.get('Key')
ks = k.split('/')
if ks[1] == '':
continue
file_name = ks[1]
print(obj.get('Key'))
li_t = Template(li_html)
insert_list.append(li_t.render(
file_url='#',
file_name=file_name
))
output_html = index_t.render(file_li=''.join(insert_list))
return output_html
def lambda_handler(event, context):
output_html = main()
return {
"statusCode": 200,
"headers": {
"Content-Type": 'text/html'
},
"isBase64Encoded": False,
"body": output_html
}
Funktionsname: download ___ download
Datei von s3 lambda herunterladen
import boto3
from botocore.exceptions import ClientError
import os
import logging
import base64
logger = logging.getLogger()
S3 = boto3.resource('s3')
TEMPLATE_AWS_S3_BUCKET_NAME = 'hogehoge-downloader'
TEMPLATE_BUCKET = S3.Bucket(TEMPLATE_AWS_S3_BUCKET_NAME)
def get_object(bucket, object_name):
"""Retrieve an object from an Amazon S3 bucket
:param bucket_name: string
:param object_name: string
:return: botocore.response.StreamingBody object. If error, return None.
"""
try:
response = bucket.Object(object_name).get()
except ClientError as e:
# AllAccessDisabled error == bucket or object not found
logging.error(e)
return None
# Return an open StreamingBody object
return response['Body'].read()
def lambda_handler(event, context):
file_name = event['queryStringParameters']['fileName']
body = get_object(TEMPLATE_BUCKET, os.path.join('files', file_name))
return {
"statusCode": 200,
"headers": {
"Content-Disposition": 'attachment;filename="{}"'.format(file_name),
"Content-Type": 'application/zip'
},
"isBase64Encoded": True,
"body": base64.b64encode(body).decode('utf-8')
}
API Gateway
--Wählen Sie REST-API als API-Typ
So gebaut.
Stellen Sie ein, dass Sie mit der Lambda-Funktion arbeiten, die die Standardauthentifizierung durchführt.
Stellen Sie wie folgt ein. Deaktivieren Sie den Autorisierungscache. (Wenn Sie es aktiviert lassen und mehrere Ressourcen festlegen, verhält es sich seltsam.)
Damit sind die Authentifizierungseinstellungen abgeschlossen. Der Rest ist in Ordnung, wenn Sie ihn mit jeder Methode festlegen.
Bereiten Sie eine Ressourcenmethode wie unten gezeigt vor.
Die detaillierten Einstellungen für jede werden unten erklärt.
/html
Aktivieren Sie die Option Lambda-Proxy-Integration verwenden. Durch Einfügen können Header usw. auf der Lambda-Seite definiert werden.
Legen Sie die Methodenanforderung für die Authentifizierung mit der Standardauthentifizierung fest.
Geändert, damit HTML in der Methodenantwort erkannt werden kann. Ändern Sie den Inhaltstyp des Antwortkörpers in "text / html".
Damit ist die Einstellung abgeschlossen.
/download
Aktivieren Sie wie bei der HTML-Seite die Option Lambda-Proxy-Integration verwenden.
Auch hier wird die Standardauthentifizierung festgelegt.
Da ich den Dateinamen erhalten möchte, der als Parameter heruntergeladen werden soll, habe ich im Parameter URL-Abfragezeichenfolge einen Parameter mit dem Namen "Dateiname" festgelegt. (Wenn Sie es obligatorisch machen möchten, überprüfen Sie es)
Der Inhaltstyp der Methodenantwort wurde geändert, da ich die Zip-Datei herunterladen möchte.
Fügen Sie abschließend den binären Medientyp aus den Einstellungen im linken Menü hinzu. Wenn Sie hier den Zielinhaltstyp festlegen, wird der Rückgabewert (base64) von Lambda in Binär konvertiert. (Sie müssen jedoch den Inhaltstyp zum Anforderungsheader oder "application / zip" hinzufügen, um zu akzeptieren.)
S3
Bucket-Name: Erstellen Sie "hogehoge-downloader" und erstellen Sie das folgende Verzeichnis.
--files
: Speichern Sie Zip-Dateien
--template
: Bereiten Sie eine HTML-Vorlagendatei vor
Die HTML-Vorlage ist unten.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Downloader</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css">
<script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
</head>
<body>
<section class="section">
<div class="container">
<div class="container">
<ul>{{ file_li }}</ul>
</div>
</div>
</section>
</body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function download(e) {
const zipUrl = 'https://xxx.aws.com/prod/download?fileName=' + this.filename;
const blob = axios.get(zipUrl, {
responseType: 'blob',
headers: {
Accept: 'application/zip'
},
}).then(response => {
window.URL = window.URL || window.webkitURL;
const uri = window.URL.createObjectURL(response.data);
const link = document.createElement('a');
link.download = this.filename;
link.href = uri;
link.click()
}).catch(error => {
console.log(error);
});
}
var links = Array.from(document.getElementsByClassName('downloadLink'));
links.map(l => l.addEventListener('click', {filename: l.dataset.filename, handleEvent: download}));
</script>
</html>
file_li.html
<li>
<a href="{{ file_url }}" class="downloadLink" data-filename="{{ file_name }}">{{ file_name }}</a>
</li>
Diese Konfiguration funktioniert jedoch nicht. Ich habe es nicht bemerkt, bis ich mich versammelt habe. .. ..
Ich habe es nicht bemerkt, bis ich den Fehler tatsächlich zusammengebaut und bestätigt habe.
Bitte überprüfen Sie diese Seite.
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/limits.html
Nutzlast aufrufen (Anfrage und Antwort) 6 MB (synchron)
Was! !! ?? ?? ?? !! !! 6 MB? ?? ?? !! !! ?? ?? ??
Dead end.
~ Schließe ~ </ FONT> ab
Ja
Nur EC2. Vorbereitet für Ubuntu 18.04.
Wir haben die Flaschen-API in dem von Docker vorbereiteten Python-Container vorbereitet. Der Prozess der grundlegenden Authentifizierung und des Herunterladens von Zip-Dateien bleibt Bottle überlassen.
Laden Sie die ZIP-Datei herunter, die sich im aktuellen Verzeichnis befindet.
app.py
import bottle
#Benutzername und Passwort für die BASIC-Authentifizierung
USERNAME = "user"
PASSWORD = "pass"
def check(username, password):
u"""
Überprüfen Sie den Benutzernamen und das Kennwort für die BASIC-Authentifizierung
@bottle.auth_basic(check)Bewerben in
"""
return username == USERNAME and password == PASSWORD
@bottle.route("/zip")
@bottle.auth_basic(check)
def zip():
zip_filename = 'files.zip'
with open(zip_filename, 'rb') as f:
body = f.read()
response.content_type = 'application/zip'
response.set_header('Content-Disposition', 'attachment; filename="{}"'.format(zip_filename))
response.set_header('Content-Length', len(body))
response.body = body
return response
if __name__ == '__main__':
bottle.run(host='0.0.0.0', port=80, debug=True)
$ docker run -p 80:80 -v $(pwd):/app -it docker-image-hogehoge python3 /app/app.py
Jetzt können Sie eine URL auch mit großer Kapazität herunterladen (obwohl es einige Zeit dauert)! !! !! !! !! !! !!
Zum Lernen! Es ist serverlos! Ich war begeistert, aber ich hätte es von Anfang an mit EC2 tun sollen. .. .. .. .. .. ..
Recommended Posts