diff --git a/src/file/file.controller.ts b/src/file/file.controller.ts index 5799bcc..fa5df45 100644 --- a/src/file/file.controller.ts +++ b/src/file/file.controller.ts @@ -10,6 +10,7 @@ import { import { createFile, deleteFile, + downloadFolder, getChildren, getFile, updateFile, @@ -215,3 +216,19 @@ export async function fileDownloadHandler( return err; } } + +export async function folderDownloadHandler( + req: FastifyRequest, + res: FastifyReply +) { + const { folderId } = req.params as { folderId: string }; + + try { + const folderTree = await downloadFolder(folderId, req.user.tenantId); + if (!folderTree) return res.code(404).send({ error: "resource not found" }); + + return res.code(200).send(folderTree); + } catch (err) { + return err; + } +} diff --git a/src/file/file.route.ts b/src/file/file.route.ts index 1286257..324c740 100644 --- a/src/file/file.route.ts +++ b/src/file/file.route.ts @@ -6,6 +6,7 @@ import { fileDownloadHandler, fileUploadS3UrlMultiPartHandler, finishMulitPartUploadHandler, + folderDownloadHandler, getChildrenHandler, getFileHandler, updateFileHandler, @@ -120,6 +121,15 @@ export async function fileRoutes(fastify: FastifyInstance) { fileDownloadHandler ); + fastify.get( + "/:folderId/downloadFolder", + { + config: { requiredClaims: ["file:download"] }, + preHandler: [fastify.authorize], + }, + folderDownloadHandler + ); + fastify.get( "/multipart", { diff --git a/src/file/file.service.ts b/src/file/file.service.ts index 787d669..f663242 100644 --- a/src/file/file.service.ts +++ b/src/file/file.service.ts @@ -1,6 +1,6 @@ import { AuthenticatedUser } from "../auth"; import { generateId } from "../utils/id"; -import { deleteFileS3 } from "../utils/s3"; +import { deleteFileS3, getFileUrlS3 } from "../utils/s3"; import { CreateFileInput, CreateFilesBatch, @@ -148,3 +148,43 @@ export async function deleteFile(fileId: string, tenantId: string) { ); } } + +type File = { + pid: String; + name: String; + type: String; + size?: Number; + children?: File[]; + downloadUrl?: String; +}; + +export async function downloadFolder(folderId: string, tenantId: string) { + async function traverseFolder(folderId: string) { + const fileTree: File[] = []; + const children = await getChildren(folderId, tenantId); + + for (const child of children) { + if (child.mimeType == "folder") { + const subTree = await traverseFolder(child.pid); + fileTree.push({ + pid: child.pid, + name: child.name, + type: "folder", + children: subTree, + }); + } else { + const downloadUrl = await getFileUrlS3(child.pid, null, false); + fileTree.push({ + pid: child.pid, + name: child.name, + type: child.mimeType, + downloadUrl, + }); + } + } + + return fileTree; + } + + return await traverseFolder(folderId); +} diff --git a/src/utils/s3.ts b/src/utils/s3.ts index 852f573..3a834fc 100644 --- a/src/utils/s3.ts +++ b/src/utils/s3.ts @@ -101,7 +101,7 @@ export async function getFileUrlS3( : undefined, }); - return await getSignedUrl(client, command, { expiresIn: 300 }); + return await getSignedUrl(client, command, { expiresIn: 900 }); } export async function deleteFileS3(key: string) {