Uploading and downloading files

MadelineProto provides wrapper methods to upload and download files that support bot API file ids.

Maximum file size is of 1.5 GB.

Sending files

To send photos and documents to someone, use the $MadelineProto->messages->sendMedia method, click on the link for more info.

The required message parameter is the caption: it can contain URLs, mentions, bold and italic text, thanks to the parse_mode parameter, that enables markdown or HTML parsing.

The media parameter contains the file path and other info about the file.

It can contain lots of various objects, here are the most important:

Security notice

Be careful when calling methods with user-provided parameters: the upload function may be used to access and send any file.
To disable automatic uploads by file name, set $MadelineProto->settings['upload']['allow_automatic_upload'] = false and upload files manually.

inputMediaUploadedPhoto

$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => [
        '_' => 'inputMediaUploadedPhoto',
        'file' => 'faust.jpg'
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

Can be used to upload photos: simply provide the photo’s file path in the file field, and optionally provide a ttl_seconds field to set the self-destruction period of the photo, even for normal chats

inputMediaUploadedDocument

$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => 'video.mp4',
        'attributes' => [
            ['_' => 'documentAttributeVideo', 'round_message' => false, 'supports_streaming' => true]
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

Can be used to upload documents, videos, gifs, voice messages, round videos, round voice messages: simply provide the file’s file path in the file field, and optionally provide a ttl_seconds field to set the self-destruction period of the photo, even for normal chats.
You must also provide the file’s mime type in the mime_type field, generate it using mime_content_type($file_path); (tip: try using an unexpected mime type to make official clients crash ;).
Use the nosound_video field if the video does not have sound (gifs).
To actually set the document type, provide one or more DocumentAttribute objects to the attributes field:

documentAttributeFilename to send a document

$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => 'file.txt',
        'attributes' => [
            ['_' => 'documentAttributeFilename', 'file_name' => 'document.txt']
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

documentAttributeImageSize to send a photo as document

$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => 'file.jpg',
        'attributes' => [
            ['_' => 'documentAttributeImageSize'],
            ['_' => 'documentAttributeFilename', 'file_name' => 'image.jpg']
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

documentAttributeAnimated to send a gif

$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => 'file.mp4',
        'attributes' => [
            ['_' => 'documentAttributeAnimated']
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

documentAttributeVideo to send a video

$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => 'video.mp4',
        'attributes' => [
            ['_' => 'documentAttributeVideo', 'round_message' => false, 'supports_streaming' => true]
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

Set round_message to true to send a round message.
You might want to manually provide square w (width) and h (height) parameters to send round videos.

documentAttributeAudio to send an audio file

$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => 'song.mp3',
        'attributes' => [
            ['_' => 'documentAttributeAudio', 'voice' => false, 'title' => 'This is magic', 'performer' => 'Daniil Gentili']
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

Set the voice parameter to true to send a voice message.

Uploading files

$MessageMedia = $MadelineProto->messages->uploadMedia([
    'media' => [
        '_' => 'inputMediaUploadedPhoto',
        'file' => 'faust.jpg'
    ],
]);

You can also only upload a file, without actually sending it to anyone, storing only the file ID for later usage.

The $MadelineProto->messages->uploadMedia function is a reduced version of the $MadelineProto->messages->sendMedia, that requires only a media parameter, with the media to upload.

The returned MessageMedia object can then be reused to resend the document using sendMedia.

$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => $MessageMedia,
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

$MessageMedia can also be a Message (the media contained in the message will be sent), an Update (the media contained in the message contained in the update will be sent).

Bot API file IDs

$MessageMedia can even be a bot API file ID, generated by the bot API, or by MadelineProto:

Actual MessageMedia objects can also be converted to bot API file IDs like this:

$botAPI_file = $MadelineProto->MTProto_to_botAPI($MessageMedia);

$botAPI_file now contains a bot API message, to extract the file ID from it use the following code:

foreach (['audio', 'document', 'photo', 'sticker', 'video', 'voice', 'video_note'] as $type) {
    if (isset($botAPI_file[$type]) && is_array($botAPI_file[$type])) {
        $method = $type;
    }
}
$result['file_type'] = $method;
if ($result['file_type'] == 'photo') {
    $result['file_size'] = $botAPI_file[$method][0]['file_size'];
    if (isset($botAPI_file[$method][0]['file_name'])) {
        $result['file_name'] = $botAPI_file[$method][0]['file_name'];
        $result['file_id'] = $botAPI_file[$method][0]['file_id'];
    }
} else {
    if (isset($botAPI_file[$method]['file_name'])) {
        $result['file_name'] = $botAPI_file[$method]['file_name'];
    }
    if (isset($botAPI_file[$method]['file_size'])) {
        $result['file_size'] = $botAPI_file[$method]['file_size'];
    }
    if (isset($botAPI_file[$method]['mime_type'])) {
        $result['mime_type'] = $botAPI_file[$method]['mime_type'];
    }
    $result['file_id'] = $botAPI_file[$method]['file_id'];
}
if (!isset($result['mime_type'])) {
    $result['mime_type'] = 'application/octet-stream';
}
if (!isset($result['file_name'])) {
    $result['file_name'] = $result['file_id'].($method === 'sticker' ? '.webp' : '');
}

Reusing uploaded files

$MadelineProto->messages->uploadMedia and bot API file IDs do not allow you to modify the type of the file to send: however, MadelineProto provides a method that can generate a file object that can be resent with multiple file types.

$inputFile = $MadelineProto->upload('filename.mp4');

The generated $inputFile can later be reused thusly:

$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => $inputFile,
        'attributes' => [
            ['_' => 'documentAttributeFilename', 'file_name' => 'video.mp4']
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);
$sentMessageVideo = $MadelineProto->messages->sendMedia([
    'peer' => '@danogentili',
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => $inputFile,
        'attributes' => [
            ['_' => 'documentAttributeVideo', 'round_message' => false, 'supports_streaming' => true]
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

In this case, we’re reusing the same InputFile to send both a document and a video, without uploading the file twice.

The concept is easy: where you would usually provide a file path, simply provide $inputFile.

Downloading files

There are multiple download methods that allow you to download a file to a directory, to a file or to a stream.

Extracting download info

$info = $MadelineProto->get_download_info($MessageMedia);

$MessageMedia can be a MessageMedia object or a bot API file ID.

Download to directory

$output_file_name = $MadelineProto->download_to_dir($MessageMedia, '/tmp/');

This downloads the given file to /tmp, and returns the full generated file path.

$MessageMedia can be either a Message, an Update, a MessageMedia object, or a bot API file ID.

Download to file

$output_file_name = $MadelineProto->download_to_file($MessageMedia, '/tmp/myname.mp4');

This downloads the given file to /tmp/myname.mp4, and returns the full file path.

$MessageMediacan be either a Message, an Update, a MessageMedia object, or a bot API file ID.

Download to browser with streams

$info = $MadelineProto->get_download_info($MessageMedia);
header('Content-Length: '.$info['size']);
header('Content-Type: '.$info['mime']);

$stream = fopen('php://output', 'w');
$MadelineProto->download_to_stream($MessageMedia, $stream, $cb, $offset, $endoffset);

This downloads the given file to the browser, sending also information about the file’s type and size.

$MessageMedia can be either a Message, an Update, a MessageMedia object, or a bot API file ID.

$stream must be a writeable stream

$cb is an optional parameter can be a callback for download progress, but it shouldn’t be used, the new FileCallback should be used instead

$offset is an optional parameter that specifies the byte from which to start downloading

$limit is an optional parameter that specifies the byte where to stop downloading (non-inclusive)

Getting progress

To get the upload/download progress in real-time, use the \danog\MadelineProto\FileCallback class:

$peer = '@danogentili';
$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => $peer,
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => new \danog\MadelineProto\FileCallback(
            'video.mp4',
            function ($progress) use ($MadelineProto, $peer) {
                $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => 'Upload progress: '.$progress.'%']);
            }
        ),
        'attributes' => [
            ['_' => 'documentAttributeVideo', 'round_message' => false, 'supports_streaming' => true]
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

$output_file_name = $MadelineProto->download_to_file(
    $sentMessage,
    new \danog\MadelineProto\FileCallback(
        '/tmp/myname.mp4',
        function ($progress) use ($MadelineProto, $peer) {
            $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => 'Download progress: '.$progress.'%']);
        }
    )
);

This will send the file video.mp4 to @danogentili: while uploading, he will receive progress messages Upload progress: 24% until the upload is complete; while downloading, he will receive progress messages Download progress: 34% until the download is complete.

A FileCallback object can be provided to uploadMedia, sendMedia, uploadProfilePicture, upload, upload_encrypted, download_to_*: the first parameter to its constructor must be the file path/object that is usually accepted by the function, the second must be a callable function or object.

You can also write your own callback class, just implement \danog\MadelineProto\FileCallbackInterface:

class MyCallback implements \danog\MadelineProto\FileCallbackInterface
{
    private $file;
    private $peer;
    private $MadelineProto;
    public function __construct($file, $peer, $MadelineProto)
    {
        $this->file = $file;
        $this->peer = $peer;
        $this->MadelineProto = $MadelineProto;
    }
    public function getFile()
    {
        return $this->file;
    }
    public function __invoke($progress)
    {
        $this->MadelineProto->messages->sendMessage(['peer' => $this->peer, 'message' => 'Progress: '.$progress.'%']);
    }
}
$peer = '@danogentili';
$sentMessage = $MadelineProto->messages->sendMedia([
    'peer' => $peer,
    'media' => [
        '_' => 'inputMediaUploadedDocument',
        'file' => new MyCallback('video.mp4', $peer, $MadelineProto),
        'attributes' => [
            ['_' => 'documentAttributeVideo', 'round_message' => false, 'supports_streaming' => true]
        ]
    ],
    'message' => '[This is the caption](https://t.me/MadelineProto)',
    'parse_mode' => 'Markdown'
]);

$output_file_name = $MadelineProto->download_to_file(
    $sentMessage,
    new MyCallback('/tmp/myname.mp4', $peer, $MadelineProto)
);

Next section