File tree Expand file tree Collapse file tree 6 files changed +29
-11
lines changed Expand file tree Collapse file tree 6 files changed +29
-11
lines changed Original file line number Diff line number Diff line change 5
5
HttpStatus ,
6
6
Inject ,
7
7
Param ,
8
+ Query ,
8
9
Request ,
9
10
Response ,
10
11
} from '@nestjs/common' ;
@@ -29,6 +30,7 @@ export class FileUrlController {
29
30
@Get ( ':fileId/:fileName?' )
30
31
async download (
31
32
@Param ( 'fileId' ) fileId : ID ,
33
+ @Query ( 'download' ) download : '' | undefined ,
32
34
@Request ( ) request : IRequest ,
33
35
@Response ( ) res : unknown ,
34
36
) {
@@ -41,7 +43,7 @@ export class FileUrlController {
41
43
42
44
// TODO authorization using session
43
45
44
- const url = await this . files . getDownloadUrl ( node ) ;
46
+ const url = await this . files . getDownloadUrl ( node , download != null ) ;
45
47
const cacheControl = this . files . determineCacheHeader ( node ) ;
46
48
47
49
const { httpAdapter } = this . httpAdapterHost ;
Original file line number Diff line number Diff line change 1
- import { ResolveField } from '@nestjs/graphql' ;
1
+ import { Args , ResolveField } from '@nestjs/graphql' ;
2
2
import { stripIndent } from 'common-tags' ;
3
3
import { URL } from 'url' ;
4
4
@@ -10,3 +10,14 @@ export const Resolver = () =>
10
10
This url could require authentication.
11
11
` ,
12
12
} ) ;
13
+
14
+ export const DownloadArg = ( ) =>
15
+ Args ( 'download' , {
16
+ description : stripIndent `
17
+ Whether the browser should download this file if opened directly
18
+
19
+ This sets the \`Content-Disposition\` header to \`attachment\` instead of \`inline\`.
20
+ https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
21
+ ` ,
22
+ defaultValue : false ,
23
+ } ) ;
Original file line number Diff line number Diff line change @@ -10,8 +10,11 @@ export class FileVersionResolver {
10
10
constructor ( protected readonly service : FileService ) { }
11
11
12
12
@FileUrl . Resolver ( )
13
- async url ( @Parent ( ) node : FileVersion ) {
14
- return await this . service . getUrl ( node ) ;
13
+ async url (
14
+ @Parent ( ) node : FileVersion ,
15
+ @FileUrl . DownloadArg ( ) download : boolean ,
16
+ ) {
17
+ return await this . service . getUrl ( node , download ) ;
15
18
}
16
19
17
20
@ResolveField ( ( ) => URL , {
Original file line number Diff line number Diff line change @@ -77,8 +77,8 @@ export class FileResolver {
77
77
}
78
78
79
79
@FileUrl . Resolver ( )
80
- async url ( @Parent ( ) node : File ) {
81
- return await this . service . getUrl ( node ) ;
80
+ async url ( @Parent ( ) node : File , @ FileUrl . DownloadArg ( ) download : boolean ) {
81
+ return await this . service . getUrl ( node , download ) ;
82
82
}
83
83
84
84
@ResolveField ( ( ) => URL , {
Original file line number Diff line number Diff line change @@ -145,27 +145,28 @@ export class FileService {
145
145
return data ;
146
146
}
147
147
148
- async getUrl ( node : FileNode ) {
148
+ async getUrl ( node : FileNode , download : boolean ) {
149
149
const url = withAddedPath (
150
150
this . config . hostUrl ,
151
151
FileUrl . path ,
152
152
isFile ( node ) ? node . latestVersionId : node . id ,
153
153
encodeURIComponent ( node . name ) ,
154
154
) ;
155
- return url . toString ( ) ;
155
+ return url . toString ( ) + ( download ? '?download' : '' ) ;
156
156
}
157
157
158
- async getDownloadUrl ( node : FileNode ) : Promise < string > {
158
+ async getDownloadUrl ( node : FileNode , download = true ) : Promise < string > {
159
159
if ( isDirectory ( node ) ) {
160
160
throw new InputException ( 'View directories via GraphQL API' ) ;
161
161
}
162
162
const id = isFile ( node ) ? node . latestVersionId : node . id ;
163
+ const disposition = download ? 'attachment' : 'inline' ;
163
164
try {
164
165
// before sending link, first check if object exists in s3
165
166
await this . bucket . headObject ( id ) ;
166
167
return await this . bucket . getSignedUrl ( GetObject , {
167
168
Key : id ,
168
- ResponseContentDisposition : `attachment ; filename="${ encodeURIComponent (
169
+ ResponseContentDisposition : `${ disposition } ; filename="${ encodeURIComponent (
169
170
node . name ,
170
171
) } "`,
171
172
ResponseContentType : node . mimeType ,
Original file line number Diff line number Diff line change @@ -12,9 +12,10 @@ export class MediaUrlResolver {
12
12
@FileUrl . Resolver ( )
13
13
async url (
14
14
@Parent ( ) media : Media ,
15
+ @FileUrl . DownloadArg ( ) download : boolean ,
15
16
@Loader ( FileNodeLoader ) files : LoaderOf < FileNodeLoader > ,
16
17
) {
17
18
const node = await files . load ( media . file ) ;
18
- return await this . service . getUrl ( node ) ;
19
+ return await this . service . getUrl ( node , download ) ;
19
20
}
20
21
}
You can’t perform that action at this time.
0 commit comments