I trying to make a api with nestjs that needs to do these things: first, i need to post a file with multer and save in the AWS S3. After, with prisma, i need to create a post that needs a description (expected from the body of the request), and i need to assign the uploaded file url to the photoUrl column. how can i do that? i need to do everything in a same service/provider? or separate them?
/// post controller
import {
Controller,
Post,
Body,
UploadedFile,
UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { PostsService } from './post.service';
@Controller('posts')
export class PostsController {
constructor(private readonly postsService: PostsService) {}
@Post()
@UseInterceptors(FileInterceptor('file'))
async createPost(
@Body('description') description: string,
@UploadedFile() file: Express.Multer.File,
) {
await this.postsService.createPost(description, file.buffer);
}
}
/// post service
// src/posts/posts.service.ts
import { Injectable } from '@nestjs/common';
import { UploadService } from '../upload/upload.service';
import { PrismaService } from 'src/database/prisma.service';
@Injectable()
export class PostsService {
constructor(
private readonly prisma: PrismaService,
private readonly uploadService: UploadService,
) {}
async createPost(description: string, file: Buffer): Promise<void> {
const filename = 'generated_filename_here'
const photoUrl = await this.uploadService.create(filename, file);
await this.prisma.post.create({
data: {
description,
photoUrl,
},
});
}
}
/// upload controller
import {
Controller,
Post,
UploadedFile,
UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { UploadService } from './upload.service';
@Controller('upload')
export class UploadController {
constructor(private readonly uploadService: UploadService) {}
@Post()
@UseInterceptors(FileInterceptor('file'))
async uploadFile(@UploadedFile() file: Express.Multer.File) {
const filename = 'generated_filename_here'; // Gere um nome de arquivo único
const photoUrl = await this.uploadService.create(filename, file.buffer);
return { photoUrl };
}
}
/// upload service
import { Injectable } from '@nestjs/common';
import { S3 } from 'aws-sdk';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class UploadService {
private readonly s3Client = new S3({
region: this.configService.getOrThrow('AWS_S3_REGION'),
});
constructor(private readonly configService: ConfigService) {
this.s3Client = new S3();
}
async create(filename: string, file: Buffer) {
const upload: S3.PutObjectRequest = {
Bucket: 'matheus-nodebucket',
Key: filename,
Body: file,
};
const result = await this.s3Client.upload(upload).promise();
return result.Location;
}
}
To context, i have the following schema from prisma:
model User {
id Int @id @default(autoincrement())
username String
password String
email String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
description String?
photoUrl String
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
i already tried separate both operations in different services and controllers but doesn't work