@@ -28,6 +28,11 @@ interface ResourceFileManagerOptions {
2828interface ResourceFileManager {
2929 listDirectory : ( slug : string , rawPath : string | undefined ) => FileTreeResponse ;
3030 readFileContent : ( slug : string , rawPath : string | undefined ) => FileContentResponse ;
31+ downloadPath : ( slug : string , rawPath : string | undefined ) => {
32+ filename : string ;
33+ contentType : string ;
34+ body : NodeJS . ReadableStream ;
35+ } ;
3136 saveFileContent : ( slug : string , request : FileSaveRequest ) => FileSaveResponse ;
3237 createFileOrFolder : ( slug : string , rawParentPath : string | undefined , name : string , kind : "file" | "directory" ) => FileNode ;
3338 uploadFileFromTempPath : ( slug : string , rawParentPath : string | undefined , name : string , tempFilePath : string ) => FileNode ;
@@ -379,6 +384,36 @@ export function createResourceFileManager(options: ResourceFileManagerOptions):
379384 return response ;
380385 }
381386
387+ function downloadPath ( slug : string , rawPath : string | undefined ) : {
388+ filename : string ;
389+ contentType : string ;
390+ body : NodeJS . ReadableStream ;
391+ } {
392+ const relativePath = normalizeRelativePath ( rawPath ?? "" , false ) ;
393+ const absolutePath = resolveTarget ( slug , relativePath ) ;
394+ if ( ! fs . existsSync ( absolutePath ) ) {
395+ throw {
396+ status : 404 ,
397+ message : "File or folder not found"
398+ } ;
399+ }
400+ assertExistingPathIsSafe ( slug , absolutePath ) ;
401+
402+ const stat = fs . statSync ( absolutePath ) ;
403+ if ( ! stat . isFile ( ) ) {
404+ throw {
405+ status : 400 ,
406+ message : "path must be a file"
407+ } ;
408+ }
409+
410+ return {
411+ filename : path . basename ( relativePath ) ,
412+ contentType : "application/octet-stream" ,
413+ body : fs . createReadStream ( absolutePath ) ,
414+ } ;
415+ }
416+
382417 function saveFileContent ( slug : string , request : FileSaveRequest ) : FileSaveResponse {
383418 const relativePath = normalizeRelativePath ( request . path , false ) ;
384419 const absolutePath = resolveTarget ( slug , relativePath ) ;
@@ -560,6 +595,7 @@ export function createResourceFileManager(options: ResourceFileManagerOptions):
560595 return {
561596 listDirectory,
562597 readFileContent,
598+ downloadPath,
563599 saveFileContent,
564600 createFileOrFolder,
565601 uploadFileFromTempPath,
0 commit comments