How to receive data sent by file with API Gateway (REST API) + Lambda (node.js v16)
curl
Send a local sample.json file with curl.
sample.json
{ "name": "takahashi", "age": 20 }
Only one file will be used in this case.
curl -X POST -F file1=@sample.json https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/
API Gateway
Configure the API Gateway settings, creating an API with the POST method of the REST API.
Set the binary media type to “multipart/form-data”.
Uncheck Lambda proxy integration in the integration request settings.
Set the following two HTTP headers
- ‘*/*’
- ‘method.request.header.Content-Type’
Under Mapping Templates, select “No template defined (recommended)” and click “Add Mapping Template”.
Enter “multipart/form-data” and save it. In Generate Template, select “Method request pass-through” and save it.
Now if you deploy, curl will issue a URL to execute.
Lambda
Next, Lambda (node.js v16) receives the json data.
Use the parse-multipart-data module.
npm i parse-multipart-data
The following data is passed to Lambda.
event["body-json"].toString()The following data is passed to Lambda. ↓ [ { filename: 'sample.json', // local filename type: 'application/octet-stream', name: 'file1', // File name specified by curl data: } ] event.params.header['content-type'] ↓ multipart/form-data; boundary=------------------------5be85402ae18ca66
From this value (event.params.header[‘content-type’]), the boundary is first obtained.
const boundary = multipart.getBoundary(event.params.header['content-type']) console.log(boundary) // ------------------------5be85402ae18ca66
multipart.parse. Specify boundary as the second argument.
const part = multipart.parse(Buffer.from(datas, "base64") ,boundary) ↓ [ { filename: 'sample.json', type: 'application/octet-stream', name: 'file1', data: } ]
The reason it comes as an array is that curl can send multiple files.
Now, if we convert part.data from Buffer to String, we can handle the local sample.json.
Lambda source.
import multipart from 'parse-multipart-data' import { StringDecoder } from "string_decoder" const decoder = new StringDecoder("utf-8") export async function handler(event, context) { const boundary = multipart.getBoundary(event.params.header['content-type']) const part = multipart.parse(Buffer.from(event["body-json"].toString(), "base64") ,boundary) const ret = decoder.write(part[0].data) // buffer→string return { statusCode: 200, body: `${ret}` } }
Test
Finally, test with curl.
You can confirm that the contents of sample.json are returned.
コメント