Are you looking to create a serverless solution for uploading JPEG images to Amazon S3 using AWS API Gateway and Lambda? This guide will walk you through creating an API Gateway endpoint that uploads JPEG images to an S3 bucket using AWS Lambda, with the added feature of using a “filename” parameter to name the S3 object. We’ll be using TypeScript to write our Lambda function, ensuring type safety and improved developer experience.
Prerequisites
Before we begin, make sure you have:
- An AWS account
- AWS CLI installed and configured
- Node.js and npm installed
- TypeScript installed globally (
npm install -g typescript
) - AWS SAM CLI installed
Step 1: Set Up the Project
First, let’s create a new directory for our project and initialize it:
mkdir aws-image-upload
cd aws-image-upload
npm init -y
npm install aws-sdk @types/aws-lambda @types/node typescript
npm install --save-dev @types/aws-sdk
Create a tsconfig.json
file in the root directory:
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
Step 2: Create the Lambda Function
Create a new file src/index.ts
and add the following code:
import { APIGatewayProxyHandler } from "aws-lambda";
import { S3 } from "aws-sdk";
const s3 = new S3();
export const handler: APIGatewayProxyHandler = async (event) => {
if (!event.body || !event.queryStringParameters?.filename) {
return {
statusCode: 400,
body: JSON.stringify({ message: "Missing file or filename parameter" }),
};
}
const filename = event.queryStringParameters.filename;
const fileContent = Buffer.from(event.body, "base64");
if (
!filename.toLowerCase().endsWith(".jpg") &&
!filename.toLowerCase().endsWith(".jpeg")
) {
return {
statusCode: 400,
body: JSON.stringify({ message: "File must be a JPEG image" }),
};
}
const params = {
Bucket: process.env.S3_BUCKET_NAME!,
Key: filename,
Body: fileContent,
ContentType: "image/jpeg",
};
try {
const result = await s3.upload(params).promise();
return {
statusCode: 200,
body: JSON.stringify({
message: "File uploaded successfully",
fileUrl: result.Location,
}),
};
} catch (error) {
console.error("Error uploading file:", error);
return {
statusCode: 500,
body: JSON.stringify({ message: "Error uploading file" }),
};
}
};
This Lambda function does the following:
- Checks for the presence of the file content and filename parameter
- Verifies that the file is a JPEG image
- Uploads the file to S3 using the provided filename
- Returns a success message with the file URL or an error message
Step 3: Create the SAM Template
Create a template.yaml
file in the root directory:
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: API Gateway for uploading JPEG images to S3
Resources:
ImageUploadFunction:
Type: AWS::Serverless::Function
Properties:
Handler: dist/index.handler
Runtime: nodejs20.x
CodeUri: ./
Environment:
Variables:
S3_BUCKET_NAME: !Ref UploadBucket
Policies:
- S3CrudPolicy:
BucketName: !Ref UploadBucket
Events:
UploadAPI:
Type: Api
Properties:
Path: /upload
Method: post
UploadBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${AWS::StackName}-uploads
AccessControl: Private
Outputs:
ApiUrl:
Description: URL of the API endpoint
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/upload"
This SAM template sets up:
- A Lambda function with the necessary permissions
- An S3 bucket for storing the uploaded images
- An API Gateway endpoint that triggers the Lambda function
Step 4: Build and Deploy
First, compile your TypeScript code:
npx tsc
Then, use SAM CLI to build and deploy your application:
sam build
sam deploy --guided
Follow the prompts to complete the deployment. Once finished, you’ll receive an API endpoint URL.
Step 5: Test Your API
You can test your new API using cURL. Replace YOUR_API_ENDPOINT
with the URL provided after deployment:
curl -X POST \
'YOUR_API_ENDPOINT?filename=test-image.jpg' \
--data-binary '@/path/to/your/image.jpg' \
-H 'Content-Type: image/jpeg'
This command sends a POST request to your API with the image file and the filename parameter.
Conclusion
Congratulations! You’ve successfully created an AWS API Gateway endpoint that uploads JPEG images to an S3 bucket using AWS Lambda and TypeScript. This serverless solution provides a scalable and efficient way to handle image uploads in your applications.
Remember to implement additional security measures such as authentication and input validation based on your specific use case.