@devstroupe/devkit-cli 1.1.14 → 1.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/boilerplates/nest-template/src/modules/storage/infra/http/storage.controller.ts +49 -0
- package/dist/boilerplates/nest-template/src/modules/storage/storage.module.ts +2 -2
- package/package.json +2 -2
- package/dist/boilerplates/nest-template/src/modules/storage/infra/http/storage-download.controller.ts +0 -38
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Controller, Get, Post, Param, Res, NotFoundException, UseInterceptors, UploadedFile, Body } from '@nestjs/common';
|
|
2
|
+
import { FileInterceptor } from '@nestjs/platform-express';
|
|
3
|
+
import { Response } from 'express';
|
|
4
|
+
import { StorageService } from '@devstroupe/devkit-nest';
|
|
5
|
+
|
|
6
|
+
@Controller('storage')
|
|
7
|
+
export class StorageController {
|
|
8
|
+
constructor(
|
|
9
|
+
private readonly storageService: StorageService,
|
|
10
|
+
) {}
|
|
11
|
+
|
|
12
|
+
@Post('upload')
|
|
13
|
+
@UseInterceptors(FileInterceptor('file'))
|
|
14
|
+
async upload(
|
|
15
|
+
@UploadedFile() file: any,
|
|
16
|
+
@Body('path') path?: string,
|
|
17
|
+
) {
|
|
18
|
+
if (!file) {
|
|
19
|
+
throw new NotFoundException('Nenhum arquivo enviado.');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const result = await this.storageService.upload(
|
|
23
|
+
{
|
|
24
|
+
originalname: file.originalname,
|
|
25
|
+
mimetype: file.mimetype,
|
|
26
|
+
buffer: file.buffer,
|
|
27
|
+
size: file.size,
|
|
28
|
+
},
|
|
29
|
+
{ path }
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@Get('download/*key')
|
|
36
|
+
async download(@Param('key') key: string, @Res() res: Response) {
|
|
37
|
+
try {
|
|
38
|
+
const result = await this.storageService.download(key);
|
|
39
|
+
|
|
40
|
+
if (result.type === 'file') {
|
|
41
|
+
return res.sendFile(result.filePath!);
|
|
42
|
+
} else {
|
|
43
|
+
return res.redirect(result.url!);
|
|
44
|
+
}
|
|
45
|
+
} catch (err: any) {
|
|
46
|
+
throw new NotFoundException(err.message || 'Arquivo não encontrado.');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Module } from '@nestjs/common';
|
|
2
|
-
import {
|
|
2
|
+
import { StorageController } from './infra/http/storage.controller';
|
|
3
3
|
|
|
4
4
|
@Module({
|
|
5
|
-
controllers: [
|
|
5
|
+
controllers: [StorageController],
|
|
6
6
|
})
|
|
7
7
|
export class StorageDownloadModule {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devstroupe/devkit-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.15",
|
|
4
4
|
"description": "DevsTroupe Development Kit CLI — scaffold NestJS+Angular projects, inject Spartan UI, generate CRUDs and audit architectural governance",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"commander": "^12.0.0",
|
|
38
38
|
"fs-extra": "^11.2.0",
|
|
39
|
-
"@devstroupe/devkit-core": "1.1.
|
|
39
|
+
"@devstroupe/devkit-core": "1.1.15"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/fs-extra": "^11.0.4",
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Controller, Get, Param, Res, NotFoundException, Inject } from '@nestjs/common';
|
|
2
|
-
import { Response } from 'express';
|
|
3
|
-
import * as path from 'path';
|
|
4
|
-
import * as fs from 'fs';
|
|
5
|
-
import { STORAGE_OPTIONS_TOKEN, StorageService } from '@devstroupe/devkit-nest';
|
|
6
|
-
|
|
7
|
-
@Controller('storage')
|
|
8
|
-
export class StorageDownloadController {
|
|
9
|
-
constructor(
|
|
10
|
-
@Inject(STORAGE_OPTIONS_TOKEN)
|
|
11
|
-
private readonly storageOptions: any,
|
|
12
|
-
private readonly storageService: StorageService,
|
|
13
|
-
) {}
|
|
14
|
-
|
|
15
|
-
@Get('download/*key')
|
|
16
|
-
async download(@Param('key') key: string, @Res() res: Response) {
|
|
17
|
-
if (this.storageOptions.driver === 'local') {
|
|
18
|
-
const storagePath = path.resolve(this.storageOptions.local?.storagePath || './storage');
|
|
19
|
-
const targetFile = path.resolve(storagePath, key);
|
|
20
|
-
const rootPrefix = storagePath.endsWith(path.sep) ? storagePath : storagePath + path.sep;
|
|
21
|
-
|
|
22
|
-
// Mitigação Directory Traversal
|
|
23
|
-
if (!targetFile.startsWith(rootPrefix)) {
|
|
24
|
-
throw new NotFoundException('Arquivo não encontrado ou acesso inválido.');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (!fs.existsSync(targetFile)) {
|
|
28
|
-
throw new NotFoundException('Arquivo não encontrado.');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return res.sendFile(targetFile);
|
|
32
|
-
} else {
|
|
33
|
-
// S3 / R2
|
|
34
|
-
const url = await this.storageService.getSignedUrl(key, 300);
|
|
35
|
-
return res.redirect(url);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|