Ajoute des fonctions de gestion de fichiers dans StorageService

Ajout des fonctions privées pour sauvegarder, vérifier, et récupérer des fichiers dans le service de stockage. Plusieurs exceptions gérées pour les erreurs courantes telles que la taille et le type de fichier.
This commit is contained in:
Mathis H (Avnyr) 2024-08-21 16:06:46 +02:00
parent c0960519ae
commit a911d2d9d5
No known key found for this signature in database
GPG Key ID: FF69BF8BF95CDD58

View File

@ -1,4 +1,95 @@
import { Injectable } from "@nestjs/common";
import { BadRequestException, Injectable, InternalServerErrorException, NotFoundException } from "@nestjs/common";
import * as crypto from "node:crypto";
import { readFile, writeFile } from 'node:fs/promises';
import { join } from "node:path";
import * as console from "node:console";
import FileType from 'file-type';
@Injectable()
export class StorageService {}
export class StorageService {
/**
* Saves the given file with a generated file name that includes a prefix,
* the checksum of the file, and the file type extension.
*
* @param {string} prefix - The prefix to include in the generated file name.
* @param {Buffer} file - The file to save.
* @returns {Promise<string>} A promise that resolves with the generated file name after the file is saved.
*/
private async save(prefix: string, file: Buffer) {
const checksum = await this.checkConditions(file)
const fileType = await FileType.fileTypeFromBuffer(file)
const fileName = `${prefix.toLowerCase()}-${checksum}.${fileType.ext.toLowerCase()}`;
await this.saveFile(fileName, file)
return fileName;
//SEC TODO Catch case
}
/**
* Calculates the checksum of a given file.
*
* @param {Buffer} file - The file for which the checksum is to be calculated.
* @return {string} - The hexadecimal representation of the checksum.
*/
private getChecksum(file: Buffer) {
return crypto.createHash('sha256').update(file).digest('hex').toLowerCase();
}
/**
* Saves a file to the specified location with the provided name.
*
* @param {string} fileName - The name of the file to be saved.
* @param {Buffer} file - The file content to be saved.
*
* @return {Promise<void>} - A promise that resolves when the file is successfully saved.
*
* @throws {InternalServerErrorException} - If there is an error while saving the file.
*/
private async saveFile(fileName: string, file: Buffer): Promise<void> {
try {
await writeFile(join(process.cwd(), 'files/', fileName), file, 'utf8');
} catch (err) {
console.error(err);
throw new InternalServerErrorException("File save failed !")
}
}
/**
* Checks the conditions for a given file.
*
* @param file - The file to check.
* @returns The checksum of the file.
* @throws BadRequestException - If the file type is invalid or the file size exceeds the limit.
*/
private async checkConditions(file: Buffer): Promise<string> {
const checksum = this.getChecksum(file)
const fileType = await FileType.fileTypeFromBuffer(file)
//TODO make file type configurable by admin
if (!fileType || !fileType.mime.startsWith('image/')) {
throw new BadRequestException('Invalid file type. Only images are allowed.');
}
//check file size is less than 2mb
const fileSize = file.byteLength;
//TODO make file size configurable by admin
if (fileSize > 2 * 1024 * 1024) {
throw new BadRequestException('File size exceeds the limit. Maximum file size allowed is 2MB.');
}
return checksum;
}
/**
* Retrieves the contents of a file as a Buffer.
*
* @param {string} fileName - The name of the file to retrieve.
* @return {Promise<Buffer>} A Promise that resolves with the contents of the file as a Buffer.
* @throws {NotFoundException} If the file could not be found.
*/
private async getFile(fileName: string): Promise<Buffer> {
try {
return await readFile(join(process.cwd(), 'files/', fileName));
} catch (err) {
throw new NotFoundException("File not found")
}
}
}