Skip to content

Commit

Permalink
Save assets and generate presigned URLs
Browse files Browse the repository at this point in the history
  • Loading branch information
paweld-iRonin committed Oct 22, 2023
1 parent 87a335b commit cc2d10b
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 6 deletions.
39 changes: 39 additions & 0 deletions migrations/1697978452568-createAsset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
MigrationInterface,
QueryRunner,
Table,
} from "typeorm"

export class CreateAsset1697978452568 implements MigrationInterface {

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(
new Table({
name: "asset",
columns: [
{
name: "id",
type: "int",
isPrimary: true,
isGenerated: true,
generationStrategy: 'increment',
},
{
name: "filename",
type: "varchar",
},
{
name: "uid",
type: "varchar",
},
],
}),
true,
)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable("asset")
}

}
33 changes: 33 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"dependencies": {
"@aws-sdk/client-s3": "^3.433.0",
"@aws-sdk/s3-request-presigner": "^3.433.0",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.1.1",
"@nestjs/core": "^10.0.0",
Expand Down
53 changes: 53 additions & 0 deletions src/companies/assets.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Injectable } from '@nestjs/common';
import { CreateAssetDto } from './dto/create-asset.dto';
import { EntityManager, Repository } from 'typeorm';
import { Asset } from './entities/asset.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { ConfigService } from "@nestjs/config";

@Injectable()
export class AssetsService {
constructor(
@InjectRepository(Asset)
private readonly assetsRepository: Repository<Asset>,
private readonly entityManager: EntityManager,
private readonly configService: ConfigService,
) {}

async create(createAssetDto: CreateAssetDto) {
const asset = new Asset({
...createAssetDto,
});
await this.entityManager.save(asset);
}

async findOne(id: number) {
const asset = await this.assetsRepository.findOne({
where: { id },
});

const s3 = new S3Client({
region: this.configService.getOrThrow('AWS_REGION'),
credentials: {
accessKeyId: this.configService.getOrThrow('AWS_ACCESS_KEY_ID'),
secretAccessKey: this.configService.getOrThrow('AWS_SECRET_KEY_ID'),
},
});

const bucketName = this.configService.getOrThrow('AWS_BUCKET');
const objectKey = asset.uid;
const expirationInSeconds = 3600;

// Generate the pre-signed URL
const command = new GetObjectCommand({
Bucket: bucketName,
Key: objectKey,
});

const url = await getSignedUrl(s3, command, { expiresIn: expirationInSeconds });

return { url, filename: asset.filename };
}
}
10 changes: 9 additions & 1 deletion src/companies/companies.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ import { UpdateCompanyDto } from './dto/update-company.dto';
import { Pagination } from './../paginate';
import { Company } from './entities/company.entity';
import { FileInterceptor } from '@nestjs/platform-express';
import { AssetsService } from './assets.service';

@Controller('companies')
export class CompaniesController {
constructor(private readonly companiesService: CompaniesService, private readonly fileUploadService: FileUploadService) {}
constructor(private readonly companiesService: CompaniesService,
private readonly fileUploadService: FileUploadService,
private readonly assetsService: AssetsService) {}

@Post()
create(@Body() createCompanyDto: CreateCompanyDto) {
Expand Down Expand Up @@ -55,4 +58,9 @@ export class CompaniesController {
uploadFile(@UploadedFile() file: Express.Multer.File) {
return this.fileUploadService.uploadFile(file.buffer, file.originalname);
}

@Get('assets/:id')
findOneAsset(@Param('id') id: string) {
return this.assetsService.findOne(+id);
}
}
6 changes: 4 additions & 2 deletions src/companies/companies.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { CompaniesService } from './companies.service';
import { CompaniesController } from './companies.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Company } from './entities/company.entity';
import { Asset } from './entities/asset.entity';
import { FileUploadService } from './file.upload.service';
import { AssetsService } from './assets.service';

@Module({
imports: [TypeOrmModule.forFeature([Company])],
imports: [TypeOrmModule.forFeature([Company, Asset])],
controllers: [CompaniesController],
providers: [CompaniesService, FileUploadService],
providers: [CompaniesService, FileUploadService, AssetsService],
})
export class CompaniesModule {}
4 changes: 4 additions & 0 deletions src/companies/dto/create-asset.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class CreateAssetDto {
filename: string;
uid: string;
}
17 changes: 17 additions & 0 deletions src/companies/entities/asset.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Asset {
@PrimaryGeneratedColumn()
id: number;

@Column()
filename: string;

@Column()
uid: string;

constructor(asset: Partial<Asset>) {
Object.assign(this, asset);
}
}
7 changes: 4 additions & 3 deletions src/companies/file.upload.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { v4 as uuid } from 'uuid';
import { AssetsService } from './assets.service';

@Injectable()
export class FileUploadService {
constructor(private readonly configService: ConfigService) {}
constructor(private readonly configService: ConfigService, private readonly assetsService: AssetsService) {}

async uploadFile(dataBuffer: Buffer, fileName: string): Promise<string> {
async uploadFile(dataBuffer: Buffer, fileName: string) {
const s3 = new S3Client({
region: this.configService.getOrThrow('AWS_REGION'),
credentials: {
Expand All @@ -25,6 +26,6 @@ export class FileUploadService {
});

const result = await s3.send(command);
return fileS3Name;
return this.assetsService.create({ filename: fileName, uid: fileS3Name });
}
}

0 comments on commit cc2d10b

Please sign in to comment.