mirror of
https://github.com/complexcaresolutions/telegram-media-bot.git
synced 2026-03-17 17:23:42 +00:00
fix: infer MIME type from file extension for Telegram downloads
Telegram's file API returns application/octet-stream instead of the actual image type. Added inferMimeType() that detects the real type from the URL extension (jpg→image/jpeg, png→image/png, etc.) when the server response Content-Type is generic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
11e91a26c1
commit
86d3eeb51f
1 changed files with 26 additions and 2 deletions
|
|
@ -3,6 +3,29 @@ import { createLogger } from './logger.js';
|
||||||
const log = createLogger('Download');
|
const log = createLogger('Download');
|
||||||
const MAX_FILE_SIZE = 20 * 1024 * 1024; // 20 MB
|
const MAX_FILE_SIZE = 20 * 1024 * 1024; // 20 MB
|
||||||
|
|
||||||
|
// Telegram's file API often returns application/octet-stream — infer from extension
|
||||||
|
const EXT_MIME_MAP: Record<string, string> = {
|
||||||
|
jpg: 'image/jpeg',
|
||||||
|
jpeg: 'image/jpeg',
|
||||||
|
png: 'image/png',
|
||||||
|
gif: 'image/gif',
|
||||||
|
webp: 'image/webp',
|
||||||
|
avif: 'image/avif',
|
||||||
|
svg: 'image/svg+xml',
|
||||||
|
pdf: 'application/pdf',
|
||||||
|
mp4: 'video/mp4',
|
||||||
|
};
|
||||||
|
|
||||||
|
function inferMimeType(url: string, headerType: string): string {
|
||||||
|
// If server returned a specific image/video/pdf type, trust it
|
||||||
|
if (headerType && !headerType.startsWith('application/octet-stream') && headerType !== 'text/plain') {
|
||||||
|
return headerType.split(';')[0].trim();
|
||||||
|
}
|
||||||
|
// Infer from URL extension
|
||||||
|
const ext = url.split(/[?#]/)[0].split('.').pop()?.toLowerCase() ?? '';
|
||||||
|
return EXT_MIME_MAP[ext] ?? headerType ?? 'application/octet-stream';
|
||||||
|
}
|
||||||
|
|
||||||
export async function downloadFile(url: string): Promise<{ buffer: Buffer; mimeType: string }> {
|
export async function downloadFile(url: string): Promise<{ buffer: Buffer; mimeType: string }> {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeout = setTimeout(() => controller.abort(), 30_000);
|
const timeout = setTimeout(() => controller.abort(), 30_000);
|
||||||
|
|
@ -23,8 +46,9 @@ export async function downloadFile(url: string): Promise<{ buffer: Buffer; mimeT
|
||||||
throw new Error(`Datei zu groß (${(arrayBuffer.byteLength / 1024 / 1024).toFixed(1)} MB). Maximum: 20 MB`);
|
throw new Error(`Datei zu groß (${(arrayBuffer.byteLength / 1024 / 1024).toFixed(1)} MB). Maximum: 20 MB`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mimeType = response.headers.get('content-type') || 'application/octet-stream';
|
const rawType = response.headers.get('content-type') || 'application/octet-stream';
|
||||||
log.debug(`Downloaded ${arrayBuffer.byteLength} bytes, type: ${mimeType}`);
|
const mimeType = inferMimeType(url, rawType);
|
||||||
|
log.info(`Downloaded ${arrayBuffer.byteLength} bytes, header: ${rawType}, resolved: ${mimeType}`);
|
||||||
|
|
||||||
return { buffer: Buffer.from(arrayBuffer), mimeType };
|
return { buffer: Buffer.from(arrayBuffer), mimeType };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue