AWS API Gateway + Lambda에서 multipart/form-data를 사용하여 바이너리 데이터(wav)를 S3로 put

하고 싶은 일



API Gateway와 Lambda를 사용하여 S3에 WAV 파일을 PUT합니다.

실현 방법



API Gateway는 multipart/form-data를 사용하여 POST 가능하므로,
WAV 파일
API 게이트웨이 -> 람다 -> S3
에서 PUT한다.

환경



AWS
API 게이트웨이
람다
S3

절차



테스트용 S3Bucket 만들기



테스트용 Bucket을 만듭니다.



Lambda 함수 만들기



이번에는 python3.6에서 작성해 보았습니다.
body-json이 Base64로 인코딩 된 WAV 파일을 보내고 있다고 가정합니다.
(자주 있는 샘플입니다만・・・)


import json
import boto3
import base64

def lambda_handler(event, context):

    s3 = boto3.resource('s3')
    bucket = s3.Bucket('multipart-test-*****')

    # バイナリがBase64にエンコードされているので、ここでデコード
    wavBody = base64.b64decode(event['body-json'])    

    key = "aaa.wav"

    bucket.put_object(
        Body = wavBody,
        Key = key
    )    

API 만들기





또한 통합 요청을 편집합니다.



매핑 템플릿을 선택합니다.



매핑 템플릿에서
템플릿이 정의되지 않은 경우 (권장)을 선택하고,
Content-Type으로
multipart/form-data
추가,
템플릿을 생성합니다.
템플릿은 "메소드 요청 패스 스루"는 기본값으로 유지됩니다.

바이너리 미디어 타입에도 잊지 않고
multipart/form-data
를 추가합니다.



이 상태에서,
API를 배포하면 완성됩니다.



조속히 URL로 호출해 봅시다.

https://*********.execute-api.ap-northeast-1.amazonaws.com/test/wav

POSTMAN에서 실험





WAV 파일을 form-data에서 POST하면 WAV 파일이 S3
만들어졌습니다.


aaa.wav

이것으로 문제는 없습니다.
하고 싶은 곳이지만,
aaa.wav는 정상적으로 재생할 수 없습니다.
다른 샘플 코드에서는 문제없이 만들어졌는데!

내가 빠진 곳이지만,
body-json에서 lambda에 보내지는 정보에는 원래의 WAV 파일의 정보 이외도 부여되고 있어
이대로 decode해도 wav 파일의 형식에 문제가 발생해 버립니다.
송신되고 있는 bytes 캐릭터 라인을 디코드해 확인하면(자) 이런 느낌이었습니다.
b'----------------------------648504498822251077984882\r\nContent-Disposition: form-data; name="file"; filename="0340.wav"\r\nContent-Type: audio/wave\r\n\r\nRIFFDs\x00\x00WAVEfmt 
~(wavdataが続く)~
\r\n----------------------------648504498822251077984882--\r\n'


파일 Parse용의 파라미터나, content 정보가 부여되고 있습니다.
WAV 파일만 추출하고 싶으므로 Bytes 문자열로
b'RIFF 다음 정보가 필요합니다.

lambda 측을 편집하고,
import json
import boto3
import base64

def lambda_handler(event, context):    

    s3 = boto3.resource('s3')
    bucket = s3.Bucket('multipart-test-matsuo')

    # バイナリがBase64にエンコードされているので、ここでデコード
    wavBody = base64.b64decode(event['body-json'])
    wavs = wavBody.split(b'\r\n')    

    key = "aaa.wav"

    bucket.put_object(
        Body = wavs[4],
        Key = key
    )    


합니다.
송신측의 WAV 파일과 같은 파일이 S3에 PUT되어,
문제없이 재생할 수있었습니다.
(파일의 바이트 수도 동일했습니다)

2019/05/08 추가



wav 파일 안에/r/n이 있으면,
분할되어 버리기 때문에,
boundary를 사용하여,
분할된 배열을 결합하도록 했습니다.
파일 이름을 키로 사용하여 Params에 부여하면,
파일명을 그대로 저장할 수 있도록 했습니다.
``
key = event['params']['querystring']['filename']

# Boundary文字列の使用
boundary = jsons[0].replace(b'-', b'')
wavBody = jsons[4]
for i in range(5, len(jsons)):
    if jsons[i].find(boundary) != -1:
        break
    else:
        wavBody = wavBody + b'\r\n' + jsons[i]

bucket.put_object(
    Body = wavBody,
    Key = key
)  

참고



htps //w w. 요츠베. 이 m/와 tch? v = BrYJlR0yR w
htps : //에서 v.ぁsss d. jp / c ぉ d / 아 ws / 스노노 - 013 - 아피가 테와 y /
htps : // 이 m / is s_y / ms / 966f720227 또는 b2 tf7f9

좋은 웹페이지 즐겨찾기