feat: refactor storage module (#521)

* feat: refactor storage module

* fix: folder need to be kebab case

* fix: comment wrong auth
This commit is contained in:
Jérémy M
2023-07-05 16:34:39 +02:00
committed by GitHub
parent 6e1ffdcc72
commit 2961fed932
74 changed files with 330 additions and 355 deletions

View File

@ -1,10 +1,9 @@
import { Controller, Get, Param, Res, UseGuards } from '@nestjs/common';
import { Controller, Get, Param, Res } from '@nestjs/common';
import { Response } from 'express';
import { checkFilePath, checkFilename } from '../file.utils';
import { FileService } from '../services/file.service';
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
@UseGuards(JwtAuthGuard)
// TODO: Add cookie authentication
@Controller('files')
export class FileController {
constructor(private readonly fileService: FileService) {}

View File

@ -1,8 +1,7 @@
import { Test, TestingModule } from '@nestjs/testing';
import { FileUploadService } from './file-upload.service';
import { S3StorageService } from 'src/integrations/s3-storage/s3-storage.service';
import { LocalStorageService } from 'src/integrations/local-storage/local-storage.service';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { FileStorageService } from 'src/integrations/file-storage/file-storage.service';
describe('FileUploadService', () => {
let service: FileUploadService;
@ -12,11 +11,7 @@ describe('FileUploadService', () => {
providers: [
FileUploadService,
{
provide: S3StorageService,
useValue: {},
},
{
provide: LocalStorageService,
provide: FileStorageService,
useValue: {},
},
{

View File

@ -1,20 +1,13 @@
import { Injectable } from '@nestjs/common';
import sharp from 'sharp';
import { S3StorageService } from 'src/integrations/s3-storage/s3-storage.service';
import { kebabCase } from 'src/utils/kebab-case';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { LocalStorageService } from 'src/integrations/local-storage/local-storage.service';
import { getCropSize } from 'src/utils/image';
import { settings } from 'src/constants/settings';
import { FileFolder } from '../interfaces/file-folder.interface';
import { FileStorageService } from 'src/integrations/file-storage/file-storage.service';
@Injectable()
export class FileUploadService {
constructor(
private readonly s3Storage: S3StorageService,
private readonly localStorage: LocalStorageService,
private readonly environmentService: EnvironmentService,
) {}
constructor(private readonly fileStorage: FileStorageService) {}
async uploadFile({
file,
@ -27,23 +20,16 @@ export class FileUploadService {
mimeType: string | undefined;
fileFolder: FileFolder;
}) {
const storageType = this.environmentService.getStorageType();
await this.fileStorage.write({
file,
name,
mimeType,
folder: fileFolder,
});
switch (storageType) {
case 's3': {
await this.uploadFileToS3(file, name, mimeType, fileFolder);
return {
name: `/${name}`,
};
}
case 'local':
default: {
await this.uploadToLocal(file, name, fileFolder);
return {
name: `/${name}`,
};
}
}
return {
name: `/${name}`,
};
}
async uploadImage({
@ -88,48 +74,4 @@ export class FileUploadService {
name: `/${name}`,
};
}
private async uploadToLocal(
file: Buffer | Uint8Array | string,
name: string,
fileFolder: FileFolder,
): Promise<void> {
const folderName = kebabCase(fileFolder.toString());
try {
const result = await this.localStorage.uploadFile({
file,
name,
folder: folderName,
});
return result;
} catch (err) {
console.log('uploadFile error: ', err);
throw err;
}
}
private async uploadFileToS3(
file: Buffer | Uint8Array | string,
name: string,
mimeType: string | undefined,
fileFolder: FileFolder,
) {
// Aws only accept bucket with kebab-case name
const bucketFolderName = kebabCase(fileFolder.toString());
try {
const result = await this.s3Storage.uploadFile({
Key: `${bucketFolderName}/${name}`,
Body: file,
ContentType: mimeType,
});
return result;
} catch (err) {
console.log('uploadFile error: ', err);
throw err;
}
}
}

View File

@ -1,7 +1,7 @@
import { Test, TestingModule } from '@nestjs/testing';
import { FileService } from './file.service';
import { S3StorageService } from 'src/integrations/s3-storage/s3-storage.service';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { FileStorageService } from 'src/integrations/file-storage/file-storage.service';
describe('FileService', () => {
let service: FileService;
@ -11,7 +11,7 @@ describe('FileService', () => {
providers: [
FileService,
{
provide: S3StorageService,
provide: FileStorageService,
useValue: {},
},
{

View File

@ -1,55 +1,14 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { S3StorageService } from 'src/integrations/s3-storage/s3-storage.service';
import { EnvironmentService } from 'src/integrations/environment/environment.service';
import { createReadStream } from 'fs';
import { join } from 'path';
import { Readable } from 'stream';
import { Injectable } from '@nestjs/common';
import { FileStorageService } from 'src/integrations/file-storage/file-storage.service';
@Injectable()
export class FileService {
constructor(
private readonly s3Storage: S3StorageService,
private readonly environmentService: EnvironmentService,
) {}
constructor(private readonly fileStorageService: FileStorageService) {}
async getFileStream(folderPath: string, filename: string) {
const storageType = this.environmentService.getStorageType();
switch (storageType) {
case 's3':
return this.getS3FileStream(folderPath, filename);
case 'local':
default:
return this.getLocalFileStream(folderPath, filename);
}
}
private async getLocalFileStream(folderPath: string, filename: string) {
const storageLocation = this.environmentService.getStorageLocalPath();
const filePath = join(
process.cwd(),
`${storageLocation}/`,
return this.fileStorageService.read({
folderPath,
filename,
);
return createReadStream(filePath);
}
private async getS3FileStream(folderPath: string, filename: string) {
try {
const file = await this.s3Storage.getFile({
Key: `${folderPath}/${filename}`,
});
if (!file || !file.Body || !(file.Body instanceof Readable)) {
throw new Error('Unable to get file stream');
}
return Readable.from(file.Body);
} catch (error) {
throw new NotFoundException('File not found');
}
});
}
}