@@ -5,17 +5,14 @@ import { File } from './entities/file.entity';
55import { InjectRepository } from '@nestjs/typeorm' ;
66import { AppException } from 'omniboxd/common/exceptions/app.exception' ;
77import { I18nService } from 'nestjs-i18n' ;
8- import { S3Client , GetObjectCommand } from '@aws-sdk/client-s3' ;
9- import { createPresignedPost , PresignedPost } from '@aws-sdk/s3-presigned-post' ;
10- import { getSignedUrl } from '@aws-sdk/s3-request-presigner' ;
8+ import { PresignedPost } from '@aws-sdk/s3-presigned-post' ;
119import { formatFileSize } from '../utils/format-file-size' ;
10+ import { S3Service } from 'omniboxd/s3/s3.service' ;
11+
12+ const s3Prefix = 'uploaded-files' ;
1213
1314@Injectable ( )
1415export class FilesService {
15- private readonly s3Client : S3Client ;
16- private readonly s3InternalClient : S3Client ;
17- private readonly s3Bucket : string ;
18- private readonly s3Prefix : string ;
1916 private readonly s3MaxFileSize : number ;
2017
2118 constructor (
@@ -24,65 +21,12 @@ export class FilesService {
2421 @InjectRepository ( File )
2522 private readonly fileRepo : Repository < File > ,
2623 private readonly i18n : I18nService ,
24+ private readonly s3Service : S3Service ,
2725 ) {
28- const accessKeyId = configService . get < string > ( 'OBB_S3_ACCESS_KEY_ID' ) ;
29- const secretAccessKey = configService . get < string > (
30- 'OBB_S3_SECRET_ACCESS_KEY' ,
31- ) ;
32- if ( ! accessKeyId || ! secretAccessKey ) {
33- throw new Error ( 'S3 credentials not set' ) ;
34- }
35-
36- const s3Endpoint = configService . get < string > ( 'OBB_S3_ENDPOINT' ) ;
37- if ( ! s3Endpoint ) {
38- throw new Error ( 'S3 endpoint not set' ) ;
39- }
40-
41- const s3InternalEndpoint = configService . get < string > (
42- 'OBB_S3_INTERNAL_ENDPOINT' ,
43- ) ;
44-
45- const s3Bucket = configService . get < string > ( 'OBB_S3_BUCKET' ) ;
46- if ( ! s3Bucket ) {
47- throw new Error ( 'S3 bucket not set' ) ;
48- }
49-
50- const s3Prefix = configService . get < string > ( 'OBB_S3_PREFIX' ) ;
51- if ( ! s3Prefix ) {
52- throw new Error ( 'S3 prefix not set' ) ;
53- }
54-
55- const s3Region = configService . get < string > ( 'OBB_S3_REGION' , 'us-east-1' ) ;
56-
5726 this . s3MaxFileSize = configService . get < number > (
5827 'OBB_S3_MAX_FILE_SIZE' ,
5928 20 * 1024 * 1024 ,
6029 ) ;
61-
62- this . s3Client = new S3Client ( {
63- region : s3Region ,
64- credentials : {
65- accessKeyId,
66- secretAccessKey,
67- } ,
68- endpoint : s3Endpoint ,
69- } ) ;
70-
71- if ( s3InternalEndpoint && s3InternalEndpoint != s3Endpoint ) {
72- this . s3InternalClient = new S3Client ( {
73- region : s3Region ,
74- credentials : {
75- accessKeyId,
76- secretAccessKey,
77- } ,
78- endpoint : s3InternalEndpoint ,
79- } ) ;
80- } else {
81- this . s3InternalClient = this . s3Client ;
82- }
83-
84- this . s3Bucket = s3Bucket ;
85- this . s3Prefix = s3Prefix ;
8630 }
8731
8832 async createFile (
@@ -121,53 +65,45 @@ export class FilesService {
12165 throw new AppException ( message , 'FILE_TOO_LARGE' , HttpStatus . BAD_REQUEST ) ;
12266 }
12367 const disposition = `attachment; filename*=UTF-8''${ encodeURIComponent ( filename ) } ` ;
124- return await createPresignedPost ( this . s3Client , {
125- Bucket : this . s3Bucket ,
126- Key : `${ this . s3Prefix } /${ fileId } ` ,
127- Conditions : [
128- [ 'content-length-range' , 0 , this . s3MaxFileSize ] ,
129- { 'content-type' : mimetype } ,
130- { 'content-disposition' : disposition } ,
131- ] ,
132- Fields : {
133- 'content-type' : mimetype ,
134- 'content-disposition' : disposition ,
135- } ,
136- Expires : 900 , // 900 seconds
137- } ) ;
68+ return await this . s3Service . generateUploadForm (
69+ `${ s3Prefix } /${ fileId } ` ,
70+ true ,
71+ mimetype ,
72+ disposition ,
73+ this . s3MaxFileSize ,
74+ ) ;
13875 }
13976
14077 private async generateDownloadUrl (
14178 namespaceId : string ,
14279 fileId : string ,
143- s3Client : S3Client ,
80+ isPublic : boolean ,
14481 ) : Promise < string > {
14582 const file = await this . getFile ( namespaceId , fileId ) ;
14683 if ( ! file ) {
14784 const message = this . i18n . t ( 'resource.errors.fileNotFound' ) ;
14885 throw new AppException ( message , 'FILE_NOT_FOUND' , HttpStatus . NOT_FOUND ) ;
14986 }
15087
151- const command = new GetObjectCommand ( {
152- Bucket : this . s3Bucket ,
153- Key : `${ this . s3Prefix } /${ fileId } ` ,
154- ResponseContentDisposition : `attachment; filename*=UTF-8''${ encodeURIComponent ( file . name ) } ` ,
155- } ) ;
156-
157- return await getSignedUrl ( s3Client , command , { expiresIn : 900 } ) ;
88+ const disposition = `attachment; filename*=UTF-8''${ encodeURIComponent ( file . name ) } ` ;
89+ return await this . s3Service . generateDownloadUrl (
90+ `${ s3Prefix } /${ fileId } ` ,
91+ isPublic ,
92+ disposition ,
93+ ) ;
15894 }
15995
16096 async generatePublicDownloadUrl (
16197 namespaceId : string ,
16298 fileId : string ,
16399 ) : Promise < string > {
164- return this . generateDownloadUrl ( namespaceId , fileId , this . s3Client ) ;
100+ return this . generateDownloadUrl ( namespaceId , fileId , true ) ;
165101 }
166102
167103 async generateInternalDownloadUrl (
168104 namespaceId : string ,
169105 fileId : string ,
170106 ) : Promise < string > {
171- return this . generateDownloadUrl ( namespaceId , fileId , this . s3InternalClient ) ;
107+ return this . generateDownloadUrl ( namespaceId , fileId , false ) ;
172108 }
173109}
0 commit comments