-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Handle upload files local and S3 aws
- Loading branch information
1 parent
8745965
commit 085066c
Showing
6 changed files
with
138 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { FastifyReply, FastifyRequest } from 'fastify' | ||
import { z } from 'zod' | ||
import { ResourceNotFoundError } from '../../use-cases/errors/ResourceNotFoundError' | ||
import { AwsS3Error } from '../../use-cases/errors/AwsS3Error' | ||
import { PrismaUsersRepository } from '../../repositories/prisma/prisma-users-repository' | ||
import { AddImageToUserUseCase } from '../../use-cases/user/addImageToUserUseCase' | ||
|
||
export async function addImageUser( | ||
request: FastifyRequest, | ||
response: FastifyReply, | ||
) { | ||
const userRepository = new PrismaUsersRepository() | ||
const addImageToUserUseCase = new AddImageToUserUseCase(userRepository) | ||
const addImageUserParamsSchema = z.object({ | ||
userId: z.string().uuid(), | ||
}) | ||
|
||
const { userId } = addImageUserParamsSchema.parse(request.params) | ||
const photo = await request.file() | ||
|
||
if (photo === undefined) { | ||
return response.status(400).send({ error: 'Fail load a photo!' }) | ||
} | ||
|
||
try { | ||
const { user } = await addImageToUserUseCase.execute({ userId, photo }) | ||
return response.status(200).send({ user }) | ||
} catch (error) { | ||
if (error instanceof ResourceNotFoundError) { | ||
return response.status(400).send({ error: 'User was not found !' }) | ||
} else if (error instanceof AwsS3Error) { | ||
return response.status(400).send({ error: error.message }) | ||
} | ||
throw error | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { User } from '@prisma/client' | ||
|
||
import { ResourceNotFoundError } from '../errors/ResourceNotFoundError' | ||
import { MultipartFile } from '@fastify/multipart' | ||
import { randomUUID } from 'node:crypto' | ||
import { env } from '../../env' | ||
import path from 'node:path' | ||
import fs from 'node:fs' | ||
import { PutObjectCommand, S3Client, S3ClientConfig } from '@aws-sdk/client-s3' | ||
import pump from 'pump' | ||
import { AwsS3Error } from '../errors/AwsS3Error' | ||
import { UserRepository } from '../../repositories/user-repository' | ||
|
||
interface AddImageToUserUseCaseRequest { | ||
userId: string | ||
photo: MultipartFile | ||
} | ||
|
||
interface AddImageToUserUseCaseResponse { | ||
user: User | ||
} | ||
|
||
export class AddImageToUserUseCase { | ||
constructor(private userRepository: UserRepository) {} | ||
|
||
async execute({ | ||
userId, | ||
photo, | ||
}: AddImageToUserUseCaseRequest): Promise<AddImageToUserUseCaseResponse> { | ||
const userToBeUpdated = await this.userRepository.findById(userId) | ||
|
||
if (!userToBeUpdated) { | ||
throw new ResourceNotFoundError() | ||
} | ||
|
||
const newFileName = randomUUID() + photo.filename.replace(/\s/g, '') | ||
let photoUrl = '' | ||
|
||
if (env.STORAGE_TYPE === 'local') { | ||
const uploadPath = path.resolve(__dirname, '..', 'tmp', 'uploads') | ||
const writeSteam = fs.createWriteStream(`${uploadPath}/${newFileName}`) | ||
await pump(photo.file, writeSteam) | ||
photoUrl = `${uploadPath}/${newFileName}` | ||
} else { | ||
const s3bucket = new S3Client({ | ||
region: env.REGION, | ||
|
||
credentials: { | ||
accessKeyId: env.ACCESS_KEY_ID, | ||
secretAccessKey: env.SECRET_ACCESS_KEY, | ||
}, | ||
} as S3ClientConfig) | ||
|
||
const putObjectCommand = new PutObjectCommand({ | ||
Bucket: env.BUCKET_NAME, | ||
Key: newFileName, | ||
Body: await photo.toBuffer(), | ||
ContentType: photo.mimetype, | ||
ACL: 'public-read', | ||
}) | ||
|
||
const publishs3Result = await s3bucket.send(putObjectCommand) | ||
|
||
if (publishs3Result.$metadata.httpStatusCode !== 200) { | ||
throw new AwsS3Error() | ||
} | ||
photoUrl = env.AWS_S3_URL + newFileName | ||
} | ||
|
||
const user = await this.userRepository.addPhotoUrl(userId, photoUrl) | ||
|
||
return { user } | ||
} | ||
} |