feat: implement temporary file handling for uploads and update tests for dynamic ID verification

This commit is contained in:
MythEclipse
2026-05-18 22:01:26 +07:00
parent cc3f85284b
commit 884710fd42
2 changed files with 37 additions and 5 deletions
+33 -2
View File
@@ -1,3 +1,4 @@
import { createReadStream, unlinkSync } from 'node:fs';
import { eq } from 'drizzle-orm';
import { nanoid } from 'nanoid';
import { db, files as fileSchema } from '../db';
@@ -33,6 +34,7 @@ export const handleUpload = async (req: Request): Promise<Response> => {
};
const handleMultipartUpload = async (req: Request): Promise<Response> => {
let tempPath = '';
try {
const formData = await req.formData();
const file = formData.get('file');
@@ -88,7 +90,12 @@ const handleMultipartUpload = async (req: Request): Promise<Response> => {
return Response.json({ error: `File size exceeds ${fileType} limit` }, { status: 400 });
}
const result = await forwardToStorage(fileBuffer, finalFileName, fileType);
// Write file to disk temporarily
tempPath = `/tmp/teleuploader-${nanoid()}`;
await Bun.write(tempPath, fileBuffer);
const fileStream = createReadStream(tempPath);
const result = await forwardToStorage(fileStream, finalFileName, fileType);
const bot = getBot();
const fileInfo = (await bot.telegram.getFile(result.telegramFileId)) as any;
@@ -129,10 +136,20 @@ const handleMultipartUpload = async (req: Request): Promise<Response> => {
} catch (error: any) {
logger.error('Multipart upload error', { error: error.message });
return Response.json({ error: error.message }, { status: 500 });
} finally {
if (tempPath) {
const p = tempPath;
setTimeout(() => {
try {
unlinkSync(p);
} catch {}
}, 50);
}
}
};
const handleJSONUpload = async (req: Request): Promise<Response> => {
let tempPath = '';
try {
const { file, fileName = 'file' } = (await req.json()) as any;
@@ -195,7 +212,12 @@ const handleJSONUpload = async (req: Request): Promise<Response> => {
return Response.json({ error: `File size exceeds ${fileType} limit` }, { status: 400 });
}
const result = await forwardToStorage(fileBytes, finalFileName, fileType);
// Write file to disk temporarily
tempPath = `/tmp/teleuploader-${nanoid()}`;
await Bun.write(tempPath, fileBytes);
const fileStream = createReadStream(tempPath);
const result = await forwardToStorage(fileStream, finalFileName, fileType);
const bot = getBot();
const fileInfo = (await bot.telegram.getFile(result.telegramFileId)) as any;
@@ -236,5 +258,14 @@ const handleJSONUpload = async (req: Request): Promise<Response> => {
} catch (error: any) {
logger.error('JSON upload error', { error: error.message });
return Response.json({ error: error.message }, { status: 500 });
} finally {
if (tempPath) {
const p = tempPath;
setTimeout(() => {
try {
unlinkSync(p);
} catch {}
}, 50);
}
}
};
+4 -3
View File
@@ -47,8 +47,9 @@ mock.module('../src/db/index', () => ({
}));
// Mock nanoid
let nanoidCounter = 0;
mock.module('nanoid', () => ({
nanoid: () => 'mocked-nanoid-id',
nanoid: () => `mocked-nanoid-id-${nanoidCounter++}`,
}));
// Mock telegram utils
@@ -124,7 +125,7 @@ describe('Upload Route Handler', () => {
expect(res.status).toBe(200);
const body = await res.json();
expect(body.public_id).toBe('mocked-nanoid-id');
expect(body.public_id).toContain('mocked-nanoid-id');
expect(body.telegram_file_id).toBe('tg-file-id-123');
expect(body.telegram_file_unique_id).toBe('tg-unique-id-abc');
expect(body.file_name).toBe('test.png');
@@ -161,7 +162,7 @@ describe('Upload Route Handler', () => {
const res = await handleUpload(req);
expect(res.status).toBe(200);
const body = await res.json();
expect(body.public_id).toBe('mocked-nanoid-id');
expect(body.public_id).toContain('mocked-nanoid-id');
expect(body.file_name).toBe('test_multi.png');
});