0

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

0 Answers0