feat: upload module (#486)
* feat: wip upload module * feat: local storage and serve local images * feat: protect against injections * feat: server local and s3 files * fix: use storage location when serving local files * feat: cross field env validation
This commit is contained in:
25
server/src/core/file/resolvers/file-upload.resolver.spec.ts
Normal file
25
server/src/core/file/resolvers/file-upload.resolver.spec.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { FileUploadResolver } from './file-upload.resolver';
|
||||
import { FileUploadService } from '../services/file-upload.service';
|
||||
|
||||
describe('FileUploadResolver', () => {
|
||||
let resolver: FileUploadResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
FileUploadResolver,
|
||||
{
|
||||
provide: FileUploadService,
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<FileUploadResolver>(FileUploadResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
60
server/src/core/file/resolvers/file-upload.resolver.ts
Normal file
60
server/src/core/file/resolvers/file-upload.resolver.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { Args, Mutation, Resolver } from '@nestjs/graphql';
|
||||
import { GraphQLUpload, FileUpload } from 'graphql-upload';
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
import { FileUploadService } from '../services/file-upload.service';
|
||||
import { UseGuards } from '@nestjs/common';
|
||||
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
||||
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
||||
import { FileFolder } from '../interfaces/file-folder.interface';
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Resolver()
|
||||
export class FileUploadResolver {
|
||||
constructor(private readonly fileUploadService: FileUploadService) {}
|
||||
|
||||
@Mutation(() => String)
|
||||
async uploadFile(
|
||||
@Args({ name: 'file', type: () => GraphQLUpload })
|
||||
{ createReadStream, filename, mimetype }: FileUpload,
|
||||
@Args('fileFolder', { type: () => FileFolder, nullable: true })
|
||||
fileFolder: FileFolder,
|
||||
): Promise<string> {
|
||||
const stream = createReadStream();
|
||||
const buffer = await streamToBuffer(stream);
|
||||
const ext = filename.split('.')?.[1];
|
||||
const id = uuidV4();
|
||||
const name = `${id}${ext ? `.${ext}` : ''}`;
|
||||
|
||||
const path = await this.fileUploadService.uploadFile({
|
||||
file: buffer,
|
||||
name,
|
||||
mimeType: mimetype,
|
||||
fileFolder,
|
||||
});
|
||||
|
||||
return path.name;
|
||||
}
|
||||
|
||||
@Mutation(() => String)
|
||||
async uploadImage(
|
||||
@Args({ name: 'file', type: () => GraphQLUpload })
|
||||
{ createReadStream, filename, mimetype }: FileUpload,
|
||||
@Args('fileFolder', { type: () => FileFolder, nullable: true })
|
||||
fileFolder: FileFolder,
|
||||
): Promise<string> {
|
||||
const stream = createReadStream();
|
||||
const buffer = await streamToBuffer(stream);
|
||||
const ext = filename.split('.')?.[1];
|
||||
const id = uuidV4();
|
||||
const name = `${id}${ext ? `.${ext}` : ''}`;
|
||||
|
||||
const path = await this.fileUploadService.uploadImage({
|
||||
file: buffer,
|
||||
name,
|
||||
mimeType: mimetype,
|
||||
fileFolder,
|
||||
});
|
||||
|
||||
return path.name;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user