質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.60%

localhostからAPIGateway→Lambdaを経由してS3に画像をアップロードしたい

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 6,683

score 1275

現在、Vueでサーバーレスアプリケーションを作成しています。
フロント側からaxiosでapigatewayにリクエストを投げてそれをlambdaに渡してS3に画像をアップロードしようとしています。

何故経由させているかというと、データベースに画像の情報を登録するためです。
なので、もしかするとS3に直接アップロードしてアップロードトリガーで処理することができるかもしれません。
とりあえずはおいておきます。
フロントエンドのリクエストの部分が以下になります。

  methods: {
    onSubmit () {
      let data = new FormData()
      data.append('title', 'test')

      for (let i = 0; i < this.files.length; i++) {
        data.append('image', this.files[i])
      }

      let config = {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }

      axios.post('apigatewayUrl', data, config)
        .then((response) => {
          console.log(response.data)
        })
        .catch((error) => {
          console.log(error)
        })
    },

lambda側は以下です。

import json
import boto3
import base64


def lambda_handler(event, context):
    # print(json.dumps(event))

    try:
        s3 = boto3.resource('s3')
        bucket = s3.Bucket('backetname')
        imageBody = base64.b64decode(event['body'])
        key = "test/cat.png"
        bucket.put_object(
            Body = imageBody,
            Key = key
        )
        print('success!')
        res = {
            "isBase64Encoded": True,
            "statusCode": 200,
            "headers": {},
            "body": json.dumps({"status": 1})
        }
        return res

    except Exception as e:
        res = {
            "isBase64Encoded": True,
            "statusCode": 200,
            "headers": {},
            "body": json.dumps({"message": str(e)})
        }
        return res

実際にリクエストを投げると以下のようなエラーが返ってきます

string argument should contain only ascii characters


調べてみるとJavascriptのFormDataは独特なパースが必要というのを知りました。
現在、lambdaはpython3を使っていますが、パースする方法が見つかりませんでした。
そもそもFormDataオブジェクトを使用して画像をpostしている例がほとんどなく、
他の方は一体どのように画像をアップロードしているのだろうかと甚だ疑問です。
localhost→apigateway→lambda→S3はちゃんと繋がっているのは確認済みです。

ここで先ほどの余談に戻るのですが、APIGatewayとlambdaを経由させるのは一般的ではないのでしょうか?
S3にトリガーを設定しておいて、そのトリガーでデータベースを更新するのが一般的でしょうか?
教えて欲しいことをまとめると、

  1. FormDataでpostしたデータをlambda(python)側でパースして保存する方法はあるか
  2. そもそもFormDataを用いない方法があってそっちの方が便利なのか
  3. そもそもPythonという選択が間違っているのか
  4. apigateway→lambdaを経由させる必要はなく、S3にトリガーを仕込むのが普通か?また、その時のデータベースに登録するのに必要な情報等は一緒に送ることができるのか
  5. 一般的なサーバーレスアプリケーションに置ける画像アップロードの仕組みはどれがメジャーなのか

よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

base64で送信しては?

  1. JavaScriptで画像をBase64エンコード、FormDataでなくJSONで送信
  2. python側で受け取ったBase64データをデコード、画像に戻してS3に保存

参考
https://qiita.com/mserizawa/items/7f1b9e5077fd3a9d336b

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/22 14:07

    回答ありがとうございます。
    JS(フロント)でbase64にエンコード可能なのでしょうか?
    以前探したのですが見つかりませんでした。

    キャンセル

  • 2019/02/22 14:11

    可能です。
    ライブラリも何も要りません。
    https://am-yu.net/2012/01/08/filedata_base64/

    キャンセル

  • 2019/03/02 17:45

    挑戦してみましたが超簡単にできました!!
    サーバーレスでやるならFormDataよりもbase64にして飛ばした方が楽ですね!
    ありがとうございました!

    キャンセル

  • 2019/03/02 18:28

    良かったです。

    キャンセル

+1

FormDataでpostしたデータをlambda(python)側でパースして保存する方法はあるか
あります.
必要ならコード描きますが,どうしますか?

そもそもFormDataを用いない方法があってそっちの方が便利なのか
エンコードしてjsonで受け取るとういうのが一般的ではあります.

そもそもPythonという選択が間違っているのか
Pythonが間違っているわけではないです.言語は各社,各人の最適なもので大丈夫です.

apigateway→lambdaを経由させる必要はなく、S3にトリガーを仕込むのが普通か?また、その時のデータベースに登録するのに必要な情報等は一緒に送ることができるのか
普通かどうかはわかりませんが,,, s3に直接PutするよりもAPIGatewayを通したほうがセキュリティ上安全かと思います.

一般的なサーバーレスアプリケーションに置ける画像アップロードの仕組みはどれがメジャーなのか
今回ご質問いただいている環境は,メジャーでよく使われる構成ですね.

APIGatewayの設定でimageは許可されていますか?

下記を参照してみてもうまくいかないですかね...
https://dev.classmethod.jp/cloud/aws/sugano-013-api-gateway/
https://qiita.com/acro5piano/items/125aeede85bc0448b600

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/20 15:26

    > ちなみにcontent-typeはimage/*ではなくmultipart/form-dataでpostしていますので画像とは関係ないと思うのですがどうでしょうか?

    私の環境では,image/* もmultipart/form-data許可していました.
    ドキュメントがなかなか見当たらず,手当たり次第に設定していましたね

    キャンセル

  • 2019/02/20 15:29

    コードはちょっと待ってくださいね.
    明日ぐらいには出来るかと.

    lambdaでflaskでAPI作って,ゴニョゴニョやってたはずです

    キャンセル

  • 2019/02/20 16:02

    なるほどです。確かに全部設定しておいたほうが間違いなさそうですね。
    ありがとうございます!flaskってlambdaで使えるんですか?
    サーバーレスで実現できるならめっちゃ便利ですね!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る