[PYTHON] POSTEZ l'image sélectionnée sur le site Web avec multipart / form-data et enregistrez-la sur Amazon S3! !!

Ce que je voulais faire

Après avoir sélectionné un fichier image sur le site Web, je voulais POSTER l'image avec des données en plusieurs parties / formulaire avec le bouton de téléchargement et l'enregistrer dans S3 sur AWS, j'ai donc compris comment le faire. Cela peut être utile si vous souhaitez utiliser les services AWS, y compris l'enregistrement d'images sur votre site Web.

Schéma de configuration global

スクリーンショット 2020-03-06 13.25.15.png

Image du site Web

スクリーンショット 2020-03-06 11.11.42.png

Langage de développement et service utilisé

Nous utilisons ** HTML, CSS, JavaScript ** comme langage de développement côté Web et ** Python 3.7 ** comme langage côté Lambda. Voici les services utilisés.

** ・ AWS Lambda ** Un service AWS qui vous permet d'exécuter un code de fonction déclenché par un événement. ** - Amazon S3 (utilisé pour enregistrer les images téléchargées et comme lieu de publication de sites Web) ** Abréviation de Simple Storage Service, service de stockage en ligne AWS

Après avoir POSTÉ l'image sous la forme de multipart / form-data sur le côté Web à l'aide d'ajax, démarrez Lambda en appuyant sur API Gateway et enregistrez l'image dans S3 avec la fonction dans Lambda. En prime, stockez le nom de fichier de l'image enregistrée dans le stockage local du site afin de pouvoir parcourir l'image enregistrée.

Procédure de création globale

  1. Créer un site Web (# web-Create Site)
  2. [Créer un compartiment pour le stockage d'images dans S3](-bucket-Créer pour le stockage d'images dans # s3-)
  3. Créez Lambda (y compris API Gateway) (Create # lambda-including api-gateway)

Cela devient la procédure.

Créer un site Web

Code complet côté site Web

Cette fois, j'ai pris la forme de POST à l'API sous la forme de multipart / form-data du côté du site Web. Nous effectuons également un traitement pour empêcher la transition vers un autre écran lorsque vous cliquez sur le bouton Soumettre et modifions le style de divers boutons.

index.html


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!--la bibliothèque jquery n'est pas corrigée-->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> 
    <title>Title</title>
    <style>
        label > input {
            display:none; /*Désactiver le style du bouton de fichier*/
        }
        label > button {
            display:none; /*Désactiver le style de bouton*/
        }

        label {
            display: inline-block;
            padding: 0.5em 1em;
            text-decoration: none;
            background: #fd9535;/*Couleur du bouton*/
            color: #FFF;
            border-bottom: solid 4px #627295;
            border-radius: 3px;
        }
        button{
            display: inline-block;
            padding: 0.5em 1em;
            text-decoration: none;
            background: #fd9535;/*Couleur du bouton*/
            color: #FFF;
            border-bottom: solid 4px #627295;
            border-radius: 3px;
        }
        label:active {
            /*Lorsque vous appuyez sur le bouton*/
            -webkit-transform: translateY(4px);
            transform: translateY(4px);/*Descendre*/
            border-bottom: none;/*Effacer la ligne*/
        }
        button:active{
            /*Lorsque vous appuyez sur le bouton*/
            -webkit-transform: translateY(4px);
            transform: translateY(4px);/*Descendre*/
            border-bottom: none;/*Effacer la ligne*/
        }
    </style>
</head>
<body>
<form action="xxx Où saisir l'URL de la passerelle API xxx" method="post" enctype="multipart/form-data" id="imgForm"  target="sendPhoto">
    <p>
        <label for ="upfile">
Veuillez sélectionner un fichier
            <input type="file" name="fileName" id="upfile" accept="image/*" capture="camera">
        </label>
        <span style="color: #ff0000;" data-mce-style="color: #ff0000;"><div><img id="thumbnail" src=""></div></span>
    </p>
    <p>
        <label for="upload">
télécharger
            <button type="submit" action="" name="save" id="upload" >upload</button>
        </label>
    </p>
    <p id="compUpload"></p>
</form>
<iframe name="sendPhoto" style="width:0px;height:0px;border:0px;"></iframe>
<script>
$('#upfile').change(function(){
if (this.files.length > 0) {
//Obtenir les informations sur le fichier sélectionné
var file = this.files[0];
//Stocker les données de fichier codées en tant qu'URL de données dans la propriété result du lecteur
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function() {
$('#thumbnail').attr('src', reader.result );
}
}
});

//Télécharger l'image
    $('#imgForm').on('submit', function(e) {
        e.preventDefault();
        var formData = new FormData($('#imgForm').get(0));
        $.ajax($(this).attr('action'), {
            type: 'post',
            processData: false,
            contentType: false,
            data: formData,
            success: document.getElementById('compUpload').innerHTML = 'Téléchargement' //Lorsque la transmission est réussie

    }).done(function(response){
        let jsonbody = JSON.parse(response.body);
            console.log('succes!');  //Quand il y a une réponse
            //Stocker le nom du fichier de réponses dans le stockage local
            var array = [];
            var obj = {
                'Clé 1': 'Valeur 1',
                'Clé 2': 'Valeur 2'
            };
            array.push(obj);
            var setjson = JSON.stringify(obj);
            localStorage.setItem('Clé', jsonbody.message);
            document.getElementById('compUpload').innerHTML = 'Téléchargement terminé'

    }).fail(function() {
            console.log('error!'); //Lorsqu'une erreur survient
        });
        return false;
    });
</script>
</body>
</html>

Copiez et collez le code ci-dessus pour créer un fichier html. Placez le fichier sur votre serveur préféré ou S3 et affichez-le. Ceci termine la création côté Web à l'exception de "Spécifier l'URL de la passerelle API".

Spécification de l'URL de la passerelle API

Le code ci-dessous est la partie spécifiée

python


<body>
<form action="xxx Où saisir l'URL de la passerelle API xxx" method="post" enctype="multipart/form-data" id="imgForm"  target="sendPhoto">

Nous ajouterons ceci lorsque nous connaîtrons l'URL de la passerelle API dans les étapes ultérieures de création de Lambda. De plus, le bouton par défaut était terne, j'ai donc changé la conception avec la balise de style en haut du code. L'affichage par défaut est masqué avec display: none; puis changé pour un nouveau design.

python


<style>
        label > input {
            display:none; /*Désactiver le style du bouton de fichier*/
        }
        label > button {
            display:none; /*Désactiver le style de bouton*/
        }

        label {
            display: inline-block;
            padding: 0.5em 1em;
            text-decoration: none;
            background: #fd9535;/*Couleur du bouton*/
            color: #FFF;
            border-bottom: solid 4px #627295;
            border-radius: 3px;
        }
        button{
            display: inline-block;
            padding: 0.5em 1em;
            text-decoration: none;
            background: #fd9535;/*Couleur du bouton*/
            color: #FFF;
            border-bottom: solid 4px #627295;
            border-radius: 3px;
        }
        label:active {
            /*Lorsque vous appuyez sur le bouton*/
            -webkit-transform: translateY(4px);
            transform: translateY(4px);/*Descendre*/
            border-bottom: none;/*Effacer la ligne*/
        }
        button:active{
            /*Lorsque vous appuyez sur le bouton*/
            -webkit-transform: translateY(4px);
            transform: translateY(4px);/*Descendre*/
            border-bottom: none;/*Effacer la ligne*/
        }
    </style>

Description de la partie de téléchargement d'image

J'utilise ajax pour télécharger des images. Si le POST côté serveur réussit, le côté Web indiquera que le téléchargement est en cours.

python


<script>
//Télécharger l'image
    $('#imgForm').on('submit', function(e) {
        e.preventDefault();
        var formData = new FormData($('#imgForm').get(0));
        $.ajax($(this).attr('action'), {
            type: 'post',
            processData: false,
            contentType: false,
            data: formData,
            success: document.getElementById('compUpload').innerHTML = 'Téléchargement' //Lorsque la transmission est réussie

    }).done(function(response){
        let jsonbody = JSON.parse(response.body);
            console.log('succes!');  //Quand il y a une réponse
            //Stocker le nom du fichier de réponses dans le stockage local
            var array = [];
            var obj = {
                'Clé 1': 'Valeur 1',
                'Clé 2': 'Valeur 2'
            };
            array.push(obj);
            var setjson = JSON.stringify(obj);
            localStorage.setItem('Clé', jsonbody.message);
            document.getElementById('compUpload').innerHTML = 'Téléchargement terminé'

    }).fail(function() {
            console.log('error!'); //Lorsqu'une erreur survient
        });
        return false;
    });
</script>

Créer un compartiment pour enregistrer des images sur S3

Utilisez S3 comme emplacement pour télécharger des fichiers image à partir du Web. Sélectionnez S3 dans AWS Management Console et créez un compartiment. Il est recommandé que la région spécifiée à ce stade soit la même que la région spécifiée lors de la création de Lambda ultérieurement. (Parce que cela peut prendre du temps pour refléter les paramètres d'une autre région) ⇨ Lien de référence Il n'y a pas de problème avec les paramètres au moment de la création par défaut, mais dans cet article, dans les paramètres d'autorisation d'accès, décochez "Bloquer tous les accès publics" et définissez pour autoriser l'accès public. (Pour afficher la réponse dans Lambda sur le Web) Si vous souhaitez définir l'autorisation d'accès individuellement, définissez-la à partir de la stratégie de compartiment après la création. スクリーンショット 2020-03-09.png

Si vous spécifiez le chemin du compartiment créé ici plus tard dans Lambda, l'image téléchargée sera supprimée.

Créer Lambda (y compris API Gateway)

Créer une fonction Lambda

Lambda exécute une fonction qui enregistre une image dans S3, déclenchée par un POST d'image côté Web. Pour ce faire, sélectionnez d'abord Lambda dans AWS Management Console et cliquez sur Créer une fonction. Au moment de sa création, cet article a été créé dans la région du nord de la Virginie. (Recommandé pour être identique à la région créée dans S3)

スクリーンショット 2020-03-09-2.png

Sur l'écran de création de fonction, ・ Créer à partir de zéro -Nom de la fonction (entrez le nom de votre fonction préférée) ・ Runtime (en utilisant Python 3.7 cette fois) · Rôle d'exécution (choisissez créer un nouveau rôle avec un accès Lambda de base)

Après avoir décidé ces derniers, cliquez sur Créer une fonction. Ici, le nom de la fonction est myFunctionName. Le rôle Exécuter accorde l'accès à S3 et à Cloud Watch, mais créez-le d'abord avec les autorisations Lambda de base et ajoutez-le ultérieurement. スクリーンショット 2020-03-09 11.18.30.png

Créer une passerelle API

Lorsque la création de la fonction est terminée, l'écran d'édition de la fonction s'ouvre. Cliquez sur ** Ajouter un déclencheur ** dans la fenêtre Designer. La fenêtre changera, alors sélectionnez ** API Gateway ** et définissez les paramètres détaillés.

スクリーンショット 2020-03-09 11.46..png

Sur l'écran Ajouter un déclencheur, avec la liste déroulante et les choix de boutons radio respectifs ・ API ⇨ Créer une nouvelle API -Sélectionnez un modèle ⇨ API REST ・ Sécurité ⇨ Ouvrir ・ Cliquez sur les paramètres supplémentaires ⇨ Ajout de ** image / png ** et ** multipart / form-data ** aux types de supports binaires Après cela, cliquez sur ** Ajouter ** en bas à droite de l'écran.

スクリーンショット 2020-03-11 17.30.25.png スクリーンショット 2020-03-11 17.32.21.png

Ensuite, vous devriez voir API Gateway ajouté à Designer comme indiqué dans l'image ci-dessous. Il s'agit d'un mécanisme dans lequel API Gateway reçoit un POST côté Web et déclenche le démarrage de la fonction Lambda.

スクリーンショット 2020-03-09 13.54..png

Lorsque vous cliquez sur API Gateway dans Designer, vous verrez un ** point de terminaison API ** commençant par https. Entrez cette URL comme [Partie incertaine de la procédure de création d'un site Web](# Le code ci-dessous est -url-). Entrez dans (partie).

スクリーンショット 2020-03-09 14.50.2.png

Ensuite, cliquez sur le lien "Nom de la fonction-API" affiché directement au-dessus du point de terminaison de l'API pour créer une méthode API. スクリーンショット 2020-03-09 14.50.26.mo.png

Configuration de la méthode POST API Gateway

Cliquez sur le lien "Nom de la fonction-API" pour ouvrir la page des paramètres API Gateway. Configurez maintenant la méthode API POST pour recevoir les fichiers au format json de votre site Web.

  1. Cliquez sur ** Créer une méthode ** dans l'action pour afficher la boîte de sélection (cliquez sur la flèche de pliage à droite du nom de la fonction)

  2. Sélectionnez ** POST ** dans la case de sélection et cliquez sur la coche

  3. Sélectionnez POST, sélectionnez la région Lambda que vous utilisez sur l'écran qui s'affiche, puis entrez le nom de la fonction que vous avez créée précédemment dans le champ de saisie ** Fonction Lambda ** et cliquez sur Enregistrer.

  4. Cliquez sur OK si une fenêtre pour ajouter des autorisations à la fonction Lambda apparaît

  5. Sélectionnez Activer CORS à partir des actions, entrez "vrai" dans Advanced Access-Control-Allow-Credentials (y compris ""), activez CORS et cliquez sur Remplacer l'en-tête CORS existant par la valeur Ajouter.

  6. Sélectionnez à nouveau ** POST **, cliquez sur ** Demande d'intégration ** sur l'écran d'exécution de la méthode, et modèle de mappage ⇨ si aucun modèle n'est défini (recommandé) ⇨ ajouter un modèle de mappage ⇨ ** multipart / Entrez les données du formulaire ** ⇨ Sélectionnez ** Méthode demande passthrough ** dans Générer le modèle et enregistrez

  7. Après avoir cliqué sur le bouton Enregistrer, sélectionnez ** Nom de la fonction ** au-dessus de TOUT, sélectionnez Déployer l'API à partir des actions, sélectionnez par défaut pour l'étape à déployer, puis cliquez sur le bouton Déployer.

Ceci termine les paramètres de l'API. Veuillez noter qu'il y a plusieurs étapes et qu'il est facile de faire des erreurs. Ensuite, nous allons passer aux paramètres du code de fonction, donc revenez à l'écran des paramètres de la fonction Lambda. Vous pouvez retourner par service ⇨ Lambda ⇨ nom de la fonction.

スクリーンショット 2020-03-10 10.20.46.png

スクリーンショット 2020-03-10 10.38.02.png

スクリーンショット 2020-03-10 10.33.35.png

スクリーンショット 2020-03-10 10.43.59.mo.png

スクリーンショット 2020-03-12 9.07.02.png

スクリーンショット 2020-03-10 11.05.43.mo.png

スクリーンショット 2020-03-12 9.21.23.png

スクリーンショット 2020-03-12 9.26.57.png

Description du code de fonction Lambda

Si vous cliquez sur le nom de la fonction dans Designer et faites défiler, il y a un élément pour écrire le code de la fonction, alors écrivez le code en Python ici. Ici, le décodage de l'image, le réglage de l'emplacement de stockage, la réponse pour acquérir le nom de l'image côté Web, etc. sont décrits.

Code de fonction complet

lambda_function.py


import json
import boto3
import base64
from datetime import datetime, timezone

def convert_b64_string_to_bynary(s):
    """Décoder base64"""

def lambda_handler(event, context):
    #Paramètre de l'emplacement de stockage des images
    s3 = boto3.resource('s3')
    bucket = s3.Bucket('xxx Nom du seau pour stocker les images xxx')

    #Le binaire est encodé en Base64, donc décodez ici
    imageBody = base64.b64decode(event['body-json'])
    TextTime = datetime.now().strftime('%Y-%m-%d-%H-%M-%S') #Définissez le nom du fichier image téléchargé sur l'heure à ce moment
    images = imageBody.split(b'\r\n',4)#Coupez uniquement la partie nécessaire avec fractionnement

    key = TextTime +".png "
    bucket.put_object(
        Body = images[4],
        Key = key
    )    
    #Valeur de retour pour obtenir le nom de l'image côté Web
    return {
        'isBase64Encoded': False,
        'statusCode': 200,
        'headers': {'Access-Control-Allow-Origin' : '*' ,
        'Content-Type' :'application/json'},
        'body': '{"message":"'+ key + '"}'
    }

Après avoir collé le code, entrez le nom du compartiment S3 dans la partie suivante et enregistrez l'état avec le bouton Enregistrer en haut à droite de l'écran.

lambda_function.py


bucket = s3.Bucket('xxx Nom du seau pour stocker les images xxx')

Définition des variables d'environnement

Définissez des variables d'environnement pour ajuster l'horodatage à l'heure japonaise. Si vous faites défiler un peu vers le bas depuis l'écran du code de fonction, vous trouverez un élément pour les variables d'environnement. Suivez les étapes ci-dessous pour définir les variables d'environnement.

  1. Cliquez sur le bouton Modifier en haut à droite de l'élément de variable d'environnement
  2. Vous serez redirigé vers la page d'édition des variables d'environnement, cliquez donc ici sur Ajouter une variable d'environnement.
  3. Entrez "TZ" pour la clé et "Asia / Tokyo" pour la valeur
  4. Cliquez sur le bouton Enregistrer en bas à droite
スクリーンショット 2020-03-09 16.15.35.png スクリーンショット 2020-03-09 16.24.54.png

Paramètres du rôle d'exécution

Si vous faites défiler un peu vers le bas à partir de l'élément de variable d'environnement, vous trouverez l'élément de paramètre de rôle d'exécution. Suivez les étapes ci-dessous pour définir le rôle d'exécution.

  1. Sélectionnez Utiliser le rôle existant dans le premier menu déroulant
  2. Assurez-vous que la stratégie avec le nom de la fonction en cours de modification est sélectionnée pour le rôle existant (service-role / function name -...)
  3. Cliquez sur le lien ci-dessous ** Afficher le rôle du nom de la fonction ** dans la console IAM
  4. Une nouvelle fenêtre s'ouvrira où vous pourrez cliquer sur ** Joindre la politique **
  5. Entrez S3 dans le champ de recherche, vérifiez AmazonS3FullAccess et cliquez sur ** Attach Policy **

スクリーンショット 2020-03-09 16.36.28.mo.png

スクリーンショット 2020-03-09 16.55.30.mo.png

スクリーンショット 2020-03-09 17.04.07.mo.png

Ceci termine tous les paramètres. Essayez de télécharger l'image à partir de l'écran Web et cela réussit si l'image est enregistrée dans le compartiment correspondant de S3. En prime, vous pouvez également vérifier que le nom du fichier est enregistré dans le stockage local au moment du téléchargement avec l'outil de développement. Veuillez l'utiliser lorsque vous utilisez un service qui spécifie le fichier téléchargé.

スクリーンショット 2020-03-12 9.56.37.png

À la fin

Cette fois, j'avais l'habitude de faire référence aux images S3 avec un service appelé Amazon Rekognition Custom Labels sur AWS, j'ai donc implémenté une telle fonction. Si vous êtes intéressé, veuillez consulter l'article ci-dessous pour la convivialité. À propos de la convivialité des étiquettes personnalisées Amazon Rekognition

Lien de référence

Pourquoi Amazon S3 renvoie-t-il une réponse de redirection temporaire HTTP 307? Comment empêcher la transition d'écran lors du traitement POST avec Form

Recommended Posts

POSTEZ l'image sélectionnée sur le site Web avec multipart / form-data et enregistrez-la sur Amazon S3! !!
POSTER l'image avec json et la recevoir avec flask
Démarrez la webcam, prenez une image fixe et enregistrez-la localement
[python] Envoyez l'image capturée de la caméra Web au serveur et enregistrez-la
Mettez à jour les données en les téléchargeant sur s3 d'aws avec une commande, et supprimez les données utilisées (en chemin)
Comment publier un blog sur Amazon S3 avec le moteur de blog statique `` Pélican '' pour Pythonista
Comment obtenir la clé sur Amazon S3 avec Boto 3, exemple de mise en œuvre, notes
GAE --Avec Python, faites pivoter l'image en fonction des informations de rotation d'EXIF et importez-la dans Cloud Storage.
Essayez de normaliser Coupez l'image avec scikit-image (bien qu'elle se fâche en chemin)
Renvoyez les données d'image avec Flask of Python et dessinez-les dans l'élément canvas de HTML
Enregistrer des images sur le Web sur un lecteur avec Python (Colab)
Je veux découper uniquement le visage d'une image de personne avec Python et l'enregistrer ~ Détection de visage et rognage avec face_recognition ~
Traitez le fichier gzip UNLOADed avec Redshift avec Python de Lambda, gzipez-le à nouveau et téléchargez-le sur S3
Prenez une image avec Pepper et affichez-la sur votre tablette
J'ai exécuté GhostScript avec python, divisé le PDF en pages et l'ai converti en image JPEG.
L'histoire de la création d'un outil pour charger une image avec Python ⇒ l'enregistrer sous un autre nom
Mettez Cabocha 0.68 dans Windows et essayez d'analyser la dépendance avec Python
Connectez-vous au VPN avec votre smartphone et éteignez / rallumez le serveur
Récupérer le csv publié avec Github Action et le publier sur les pages Github
Convertissez la feuille de calcul en CSV et importez-la dans Cloud Storage avec Cloud Functions
Obtenez des taux de change réguliers avec Heroku et téléchargez des journaux sur Amazon S3
Comment enregistrer les informations de point caractéristique de l'image dans un fichier et l'utiliser pour la mise en correspondance
Ajouter des lignes et du texte sur l'image
Le fichier édité avec vim était en lecture seule, mais je veux le sauvegarder
Fabriquez un thermomètre avec Raspberry Pi et rendez-le visible sur le navigateur Partie 3
[Python] Comment enregistrer des images sur le Web à la fois avec Beautiful Soup
J'ai fait un modèle de classification d'images et essayé de le déplacer sur mobile
Je souhaite convertir du texte horizontal en texte vertical et le publier sur Twitter, etc.
Gratter l'holojour et l'afficher dans la CLI
Coupez l'image aux coins arrondis avec pythonista
Texte de l'image et publication sur slack (python slackbot)
Générer et publier des données d'image factice avec Django
J'ai essayé de sauvegarder les données avec discorde
Crop Numpy.ndarray et enregistrez-le en tant qu'image
Introduction à Python avec Atom (en route)
Enregistrer l'objet dans un fichier avec pickle
Enregistrez les résultats de la recherche sur Twitter au format CSV.
De l'introduction de Flask sur CentOS au service sur Nginx et uWSGI
Lisez le fichier csv avec le notebook jupyter et écrivez le graphique l'un sur l'autre
Il est facile d'exécuter SQL avec Python et de générer le résultat dans Excel
Il est difficile d'installer un écran vert, je n'ai donc découpé que le visage et l'ai superposé sur l'image de fond
[Python] Enregistrez le résultat du scraping Web de la page produit Mercari sur Google Colab dans une feuille de calcul Google et affichez également l'image du produit.