Introduction
If you saw my previous post, I showed you how to upload files to AWS S3 using NodeJS, but that isn't actually the most efficient way to handle file uploads. The best way to handle secure file uploads to AWS S3 is by using Presigned URLs.
How the process works:
- The Frontend requests an upload link from the server.
- NestJS generates a temporary, short-lived URL from AWS.
- The Frontend uses that URL to PUT the file directly to S3. This saves server resources because the file data doesn't have to pass through your backend.
Prerequisites
If you are new to AWS S3, please check out my previous posts. You’ll need to understand the basics, including how to set up your AWS Access Key ID, AWS Secret Access Key, and how to create an S3 Bucket before moving forward.
Implementation Details
First, install the NestJS CLI and create a new project:
npm install -g @nestjs/cli
nest new {project name}
Create a .env file and add your AWS credentials:
REGION = {REGION}
ACCESS_KEY_ID = {ACCESS_KEY_ID}
SECRET_ACCESS_KEY = {SECRET_ACCESS_KEY}
BUCKET = {BUCKET}
Next, create the s3.service.ts file. This service handles the logic for communicating with AWS:
import {Injectable} from '@nestjs/common'
import {getSignedUrl} from '@aws-sdk/s3-request-presigner'
import {ConfigService} from '@nestjs/config'
import {
S3Client,
PutObjectCommand,
ListObjectsV2Command,
GetObjectCommand,
} from '@aws-sdk/client-s3'
@Injectable()
export class S3Service {
private s3Client: S3Client
Bucket = ''
constructor(private configService: ConfigService) {
const region = this.configService.get<string>('REGION') || ''
const accessKeyId = this.configService.get<string>('ACCESS_KEY_ID') || ''
const secretAccessKey =
this.configService.get<string>('SECRET_ACCESS_KEY') || ''
this.Bucket = this.configService.get<string>('BUCKET') || ''
this.s3Client = new S3Client({
region,
credentials: {
accessKeyId,
secretAccessKey,
},
})
}
async createPresignedUrl(fileName: string) {
const command = new PutObjectCommand({
Bucket: this.Bucket,
Key: fileName,
})
const url = await getSignedUrl(this.s3Client, command, {expiresIn: 60})
return {url}
}
async listFiles() {
const command = new ListObjectsV2Command({
Bucket: this.Bucket,
})
const {Contents} = await this.s3Client.send(command)
if (!Contents) return []
const fileList = await Promise.all(
Contents.map(async file => {
const getCommand = new GetObjectCommand({
Bucket: this.Bucket,
Key: file.Key,
})
return {
fileName: file.Key,
size: file.Size,
lastModified: file.LastModified,
viewUrl: await getSignedUrl(this.s3Client, getCommand, {
expiresIn: 3600,
}),
}
})
)
return fileList
}
}
As you can see, there are two main functions here:
- createPresignedUrl: This generates a link for uploading files to the bucket. For security, this link is only valid for 60 seconds.
- listFiles: This retrieves a list of all files in your bucket. It provides access links that remain valid for 3,600 seconds (1 hour).
Now, set up the s3.controller.ts to create your API endpoints:
import {Controller, Get, Query} from '@nestjs/common'
import {S3Service} from 'src/service/s3.service'
@Controller('s3')
export class S3Controller {
constructor(private readonly s3Service: S3Service) {}
@Get('presigned-url')
async getUploadUrl(@Query('fileName') fileName: string) {
return this.s3Service.createPresignedUrl(fileName)
}
@Get('files')
async listFiles() {
return this.s3Service.listFiles()
}
}
Finally, update your app.module.ts to register the new service and controller:
import {Module} from '@nestjs/common'
import {ConfigModule} from '@nestjs/config'
import {AppController} from './app.controller'
import {AppService} from './app.service'
import {S3Controller} from './controller/s3.controller'
import {S3Service} from './service/s3.service'
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,ConfigModule
envFilePath: '.env',
}),
],
controllers: [AppController, S3Controller],
providers: [AppService, S3Service],
})
export class AppModule {}
Testing the Result
Request a Presigned URL: Call your API to get the temporary upload link.
Upload to S3: PUT the file using that URL.
Verify: Use the files endpoint to see your list of uploaded files.
You can use these links to view your files directly in your web browser.
You can view the files you have successfully uploaded in your S3 Bucket.
Feel free to leave your thoughts in the comments section! Don't forget to like, share, and follow for more helpful content in the future.
See more articles here.
Comments
Post a Comment