import { inject } from '@loopback/core' ; import { get , HttpErrors , oas , param , Response , RestBindings , } from '@loopback/rest' ; import fs from 'fs' ; import path from 'path' ; import { promisify } from 'util' ; import { STORAGE_DIRECTORY } from '../keys' ; const readdir = promisify ( fs . readdir ) ; /**
 * A controller to handle file downloads using multipart/form-data media type
 */ export class FileDownloadController { constructor ( @ inject ( STORAGE_DIRECTORY ) private storageDirectory ) { } @ get ( '/files' , { responses : { 200 : { content : { 'application/json' : { schema : { type : 'array' , items : { type : 'string' , } , } , } , } , description : 'A list of files' , } , } , } ) async listFiles ( ) { const files = await readdir ( this . storageDirectory ) ; return files ; } @ get ( '/files/{filename}' ) @ oas . response . file ( ) downloadFile ( @ param . path . string ( 'filename' ) fileName , @ inject ( RestBindings . Http . RESPONSE ) response ) { const file = this . validateFileName ( fileName ) ; response . download ( file , fileName ) ; return response ; } param fileName private validateFileName ( fileName ) { const resolved = path . resolve ( this . storageDirectory , fileName ) ; if ( resolved . startsWith ( this . storageDirectory ) ) return resolved ; throw new HttpErrors . BadRequest ( `Invalid file name: ${ fileName }` ) ; } }