refactor: rename temp-chunks to temp-uploads and update related configurations

- Changed references from 'temp-chunks' to 'temp-uploads' across .dockerignore, Dockerfile, and various configuration files for consistency.
- Introduced a new directories configuration file to manage directory paths more effectively.
- Updated file handling in the server code to utilize streaming for uploads and downloads, improving performance and memory management.
- Enhanced cleanup processes for temporary directories to maintain a tidy file structure.
This commit is contained in:
Daniel Luiz Alves
2025-07-06 00:06:09 -03:00
parent c9a9f1d6cf
commit 95939f8f47
21 changed files with 296 additions and 217 deletions

View File

@@ -65,14 +65,8 @@ export class FilesystemController {
return reply.status(400).send({ error: "Invalid or expired upload token" });
}
const contentLength = parseInt(request.headers["content-length"] || "0");
const isLargeFile = contentLength > 50 * 1024 * 1024;
if (isLargeFile) {
await this.uploadLargeFile(request, provider, tokenData.objectName);
} else {
await this.uploadSmallFile(request, provider, tokenData.objectName);
}
// Use streaming for all files to avoid loading into RAM
await this.uploadFileStream(request, provider, tokenData.objectName);
provider.consumeUploadToken(token);
reply.status(200).send({ message: "File uploaded successfully" });
@@ -82,99 +76,9 @@ export class FilesystemController {
}
}
private async uploadLargeFile(request: FastifyRequest, provider: FilesystemStorageProvider, objectName: string) {
const filePath = provider.getFilePath(objectName);
const dir = path.dirname(filePath);
await fs.promises.mkdir(dir, { recursive: true });
const tempPath = `${filePath}.tmp`;
const writeStream = fs.createWriteStream(tempPath);
const encryptStream = provider.createEncryptStream();
try {
await pipeline(request.raw, encryptStream, writeStream);
await fs.promises.rename(tempPath, filePath);
} catch (error) {
try {
await fs.promises.unlink(tempPath);
} catch (cleanupError) {
console.error("Error deleting temp file:", cleanupError);
}
throw error;
}
}
private async uploadSmallFile(request: FastifyRequest, provider: FilesystemStorageProvider, objectName: string) {
const body = request.body as any;
if (Buffer.isBuffer(body)) {
if (body.length === 0) {
throw new Error("No file data received");
}
await provider.uploadFile(objectName, body);
return;
}
if (typeof body === "string") {
const buffer = Buffer.from(body, "utf8");
if (buffer.length === 0) {
throw new Error("No file data received");
}
await provider.uploadFile(objectName, buffer);
return;
}
if (typeof body === "object" && body !== null && !body.on) {
const buffer = Buffer.from(JSON.stringify(body), "utf8");
if (buffer.length === 0) {
throw new Error("No file data received");
}
await provider.uploadFile(objectName, buffer);
return;
}
if (body && typeof body.on === "function") {
const chunks: Buffer[] = [];
return new Promise<void>((resolve, reject) => {
body.on("data", (chunk: Buffer) => {
chunks.push(chunk);
});
body.on("end", async () => {
try {
const buffer = Buffer.concat(chunks);
if (buffer.length === 0) {
throw new Error("No file data received");
}
await provider.uploadFile(objectName, buffer);
resolve();
} catch (error) {
console.error("Error uploading small file:", error);
reject(error);
}
});
body.on("error", (error: Error) => {
console.error("Error reading upload stream:", error);
reject(error);
});
});
}
try {
const buffer = Buffer.from(body);
if (buffer.length === 0) {
throw new Error("No file data received");
}
await provider.uploadFile(objectName, buffer);
} catch (error) {
throw new Error(`Unsupported request body type: ${typeof body}. Expected stream, buffer, string, or object.`);
}
private async uploadFileStream(request: FastifyRequest, provider: FilesystemStorageProvider, objectName: string) {
// Use the provider's streaming upload method directly
await provider.uploadFileFromStream(objectName, request.raw);
}
async download(request: FastifyRequest, reply: FastifyReply) {