Sending & Receiving Files
Master file handling in your Telegram bot with Televerse.
Working with files is a fundamental part of building Telegram bots. Whether you're sending photos, videos, documents, or receiving files from users, Televerse makes this process straightforward with the InputFile class and context-aware methods.
Telegram File Upload Principles
According to the Telegram Bot API, there are three main ways to send files:
- File ID: If the file is already stored on Telegram's servers, use its
file_id. No size limit when using this method. - URL: Provide a publicly accessible URL. Telegram downloads and sends it for you. Size limit: 5 MB for photos, 20 MB for other types.
- Upload (multipart/form-data): Upload a local file directly. Size limit: 10 MB for photos, 50 MB for other types.
The InputFile Class
The InputFile class is your gateway to sending files with Televerse. It supports all three upload methods through dedicated constructors.
Constructors
InputFile.fromFileId- Use a file already on Telegram serversInputFile.fromUrl- Send a file from a URLInputFile.fromFile- Upload a localFileobjectInputFile.fromBytes- Upload raw bytes with a name
import 'package:televerse/televerse.dart';
import 'dart:io';
// From a file ID (already on Telegram servers)
final photo = InputFile.fromFileId('AgACAgUAAxkBAAIvAWbUio...QADNQQ');
// From a URL
final photo = InputFile.fromUrl('https://example.com/photo.jpg');
// From a local file
final file = File('assets/photo.jpg');
final photo = InputFile.fromFile(file);
// From bytes
final bytes = file.readAsBytesSync();
final photo = InputFile.fromBytes(bytes, name: 'photo.jpg');Note: A file_id is unique to your bot. The same file can have different IDs across bots. While you can sometimes use file IDs from other bots, it's not guaranteed to work.
Sending Files
Once you have an InputFile, you can send it using Context methods. Televerse provides convenient reply methods for all file types.
Sending Photos
bot.command('photo', (ctx) async {
// Using a file ID
final photo = InputFile.fromFileId('AgACAgUAAxkBAAIvAWbUio...QADNQQ');
await ctx.replyWithPhoto(photo);
// Using a URL
final urlPhoto = InputFile.fromUrl(
'https://televerse.weaverlabs.ca/assets/lockup-with-bg.png',
);
await ctx.replyWithPhoto(urlPhoto, caption: 'From URL! 🌐');
// Using a local file
final localPhoto = InputFile.fromFile(File('assets/sunset.jpg'));
await ctx.replyWithPhoto(
localPhoto,
caption: 'Beautiful sunset! 🌅',
parseMode: ParseMode.markdown,
);
});Sending Documents
Documents are perfect for PDFs, spreadsheets, or any general file type.
bot.command('document', (ctx) async {
final document = InputFile.fromFile(File('reports/monthly.pdf'));
await ctx.replyWithDocument(
document,
caption: 'Monthly Report - January 2024',
);
});Sending Videos
Send video files with optional thumbnails and streaming support.
bot.command('video', (ctx) async {
final video = InputFile.fromFile(File('videos/demo.mp4'));
await ctx.replyWithVideo(
video,
caption: 'Check out this demo! 🎥',
supportsStreaming: true,
thumbnail: InputFile.fromFile(File('thumbnails/demo-thumb.jpg')),
);
});Sending Audio
Audio files support metadata like performer, title, and duration.
bot.command('audio', (ctx) async {
final audio = InputFile.fromFile(File('music/song.mp3'));
await ctx.replyWithAudio(
audio,
caption: 'Enjoy this track! 🎵',
performer: 'Artist Name',
title: 'Song Title',
duration: 180, // 3 minutes
);
});Media Groups (Albums)
Send 2-10 photos or videos as an album using replyWithMediaGroup.
bot.command('album', (ctx) async {
final media = [
InputMediaPhoto(media: InputFile.fromFile(File('photos/1.jpg'))),
InputMediaPhoto(
media: InputFile.fromFile(File('photos/2.jpg')),
caption: 'Photo 2 with caption',
),
InputMediaPhoto(media: InputFile.fromFile(File('photos/3.jpg'))),
];
await ctx.replyWithMediaGroup(media);
});Voice Messages & Video Notes
Telegram supports special file types for voice messages and rounded video notes.
// Sending voice messages
bot.command('voice', (ctx) async {
final voice = InputFile.fromFile(File('voice/greeting.ogg'));
await ctx.replyWithVoice(voice, duration: 5);
});
// Sending video notes (rounded videos)
bot.command('videonote', (ctx) async {
final videoNote = InputFile.fromFile(File('notes/message.mp4'));
await ctx.replyWithVideoNote(
videoNote,
duration: 10,
);
});Receiving Files
When users send files to your bot, you can access file information and download files easily.
Getting File Information
Use the getMessageFile() context method to retrieve file metadata. This method automatically detects the file type (photo, document, video, etc.) and returns the File object.
bot.on(bot.filters.photo, (ctx) async {
// Get the file information
final file = await ctx.getMessageFile();
if (file != null) {
print('File ID: ${file.fileId}');
print('File size: ${file.fileSize} bytes');
print('File path: ${file.filePath}');
}
});The getMessageFile() method works with:
- Photos (returns the largest size)
- Documents
- Audio files
- Videos
- Animations (GIFs)
- Voice messages
- Video notes
- Stickers
Downloading Files
Once you have the File object, you can download it to your server for processing.
bot.on(bot.filters.document, (ctx) async {
await ctx.reply('Processing your document...');
// Get the file information
final file = await ctx.getMessageFile();
if (file != null) {
// Get the download URL
final url = file.getDownloadUrl(bot.token);
// Or download the file directly
final io.File downloaded = await file.download(token: bot.token);
// Process the file
print('Downloaded to: ${downloaded.path}');
// You can now read, analyze, or transform the file
final bytes = await downloaded.readAsBytes();
print('File size: ${bytes.length} bytes');
await ctx.reply('Document processed successfully! ✅');
}
});Important: Download links expire after 1 hour. If you need a fresh link, call getMessageFile() or api.getFile() again.
Practical Example: Video Handler
Here's a complete example that receives a video and provides a download button:
bot.on(bot.filters.video, (ctx) async {
await ctx.reply('Got it!');
final video = ctx.msg!.video!;
print('Video dimensions: ${video.width}x${video.height}');
print('Duration: ${video.duration} seconds');
// Get the file for downloading
final file = await ctx.getMessageFile();
if (file != null) {
// Create a download button
final url = file.getDownloadUrl(bot.token);
await ctx.reply(
'Tap the button to download the video.',
replyMarkup: InlineKeyboard().addUrl('Download Now', url),
);
}
});Using the Raw API
If you're not working within a context (e.g., scheduled tasks), you can use the Raw API directly:
// Send a photo
await bot.api.sendPhoto(
ChatID(123456789),
InputFile.fromFile(File('photo.jpg')),
caption: 'Direct API call',
);
// Get file information by file ID
final file = await bot.api.getFile('AgACAgUAAxkBAAIvAWbUio...QADNQQ');
final downloaded = await file.download(token: bot.token);