1
1
import { Application } from '@feathersjs/express' ;
2
2
import { Params } from '@feathersjs/feathers' ;
3
3
import { v4 } from 'uuid' ;
4
+ import axios from 'axios' ;
5
+ import fs from 'fs' ;
6
+ import path from 'path' ;
7
+ import { User } from 'which-types' ;
4
8
5
9
// Use require to avoid bug
6
10
// https://stackoverflow.com/questions/62611373/heroku-crashes-when-importing-aws-sdk
@@ -13,15 +17,68 @@ export default class Files {
13
17
bucket ! : string ;
14
18
15
19
async find ( params : Params ) : Promise < string > {
20
+ const path = this . generateS3Path ( params . user ?. username ) ;
21
+ return this . getUploadUrl ( path ) ;
22
+ }
23
+
24
+ public isS3url ( url : string ) : boolean {
25
+ return url . startsWith ( 'https://${this.bucket}.s3' ) ;
26
+ }
27
+
28
+ public generateS3Path ( prefix = '' , ext = 'png' ) : string {
29
+ const key = v4 ( ) ;
30
+ const fileName = `${ key } .${ ext } ` ;
31
+ return prefix ? `${ prefix } /${ fileName } ` : fileName ;
32
+ }
33
+
34
+ async getUploadUrl ( path : string ) : Promise < string > {
16
35
// Return signed upload URL
17
36
return this . s3 . getSignedUrl ( 'putObject' , {
18
37
Bucket : this . bucket ,
19
- Key : ` ${ params . user ?. username } / ${ v4 ( ) } .png` ,
38
+ Key : path ,
20
39
ContentType : 'image/*' ,
21
40
Expires : 300 ,
22
41
} ) ;
23
42
}
24
43
44
+ async getDownloadUrl ( path : string ) : Promise < string > {
45
+ return this . getUploadUrl ( path ) . then ( ( url : string ) => {
46
+ const queryIndex = url . indexOf ( '?' ) ;
47
+ return url . slice ( 0 , queryIndex ) ;
48
+ } )
49
+ }
50
+
51
+ private createTmpDir ( ) {
52
+ if ( ! fs . existsSync ( 'tmp' ) ) fs . mkdirSync ( 'tmp' ) ;
53
+ }
54
+
55
+ async downloadFile ( url : string ) : Promise < string > {
56
+ return new Promise ( async ( resolve , reject ) => {
57
+ this . createTmpDir ( ) ;
58
+ const filePath = `tmp/${ v4 ( ) } ` ;
59
+ const fileStream = fs . createWriteStream ( filePath ) ;
60
+ const response = await axios . get ( url , { responseType : 'stream' } )
61
+ response . data . pipe ( fileStream )
62
+ . on ( 'error' , reject )
63
+ . on ( 'close' , ( ) => resolve ( filePath ) ) ;
64
+ } ) ;
65
+ }
66
+
67
+ async uploadFileToS3 ( filePath : string , s3Path : string ) {
68
+ const fileStream = fs . createReadStream ( filePath ) ;
69
+ const request = this . s3 . upload ( {
70
+ Bucket : this . bucket ,
71
+ Key : s3Path ,
72
+ Body : fileStream ,
73
+ ContentType : 'image/png'
74
+ } ) ;
75
+ request . on ( 'httpUploadProgress' , progress => {
76
+ console . log ( 'progress' , progress ) ;
77
+ } )
78
+ await request . promise ( ) ;
79
+ return this . getDownloadUrl ( s3Path ) ;
80
+ }
81
+
25
82
setup ( app : Application ) : void {
26
83
this . app = app ;
27
84
this . s3 = new S3 ( {
0 commit comments