Получение ботом медиа-файлов и сохранение их на своем сервере

В своей работе над ботом, который проводит розыгрыши, мне потребовалось сохранять у себя на сервере файлы, присылаемые пользователями.  Очень интересный и простой процесс получился.

У Telegram Bot Api для этого есть специальный метод getFile. На входе он получает file_id, на выходе объект File.

Параметров file_id у картинки может быть больше одного, потому как телеграм присылает несколько вариантов размеров картинки, последний всегда оригинал. При загрузке картинки в бот приходит информация в виде объекта Photo, в котором лежит массив объектов PhotoSize

Наш бот будет принимать только команду /start и картинку, на остальные запросы он будет "ругаться".  Чтобы определить, что нам пришло в нашем уже знакомом по предыдущим статьям методе init() будем проверять ключи массива пришедших данных. Для реализации задуманного нам нужен только объект Message

<?php
    // проверяем если пришло сообщение
    if (array_key_exists('message', $data)) {
        //если пришла команда /start
        if ($data['message']['text'] == "/start") {
            $this->sendMessage($chat_id, "Приветствую! Загрузите картинку.");
        } elseif (array_key_exists('photo', $data['message'])) {
            // если пришла картинка то сохраняем ее у себя
            $text = $this->getPhoto($data['message']['photo'])
                ? "Спасибо! Можете еще загрузить мне понравилось их сохранять."
                : "Что-то пошло не так, попробуйте еще раз";
            // отправляем сообщение о результате   
            $this->sendMessage($chat_id, $text);
        } else {
            // если пришло что-то другое
            $this->sendMessage($chat_id, "Не понимаю команду! Просто загрузите картинку.");
        }
    }
?>


Картинки мы будем сохранять в директории img, располагается она рядом с файлом index.php в котором наш код.

.
..
[ img ]
index.php


В случае если прислали картинку, то мы передаем массив объектов PhotoSize в метод getPhoto(), он вернет результат в boolean. Внутри метода происходит 2 действия:

  1. через метод getPhotoPath() получаем расположение файла на сервере Telegram
  2. через метод copyPhoto() копируем картинку к себе на сервер

Картинка располагается на сервере Telegram по стандартному пути:

https://api.telegram.org/file/bot<token>/<file_path>


Выводит картинку по этому пути где-либо в сети не рекомендую, так как будет доступен ваш токен от бота. 

Сохранять себе на сервер мы будем оригинал, поэтому нам надо узнать количество элементов в массиве, использовать будем функцию count()

Чтобы получить расширение файла, будем разбивать file_path в массив по знаку . функцией explode() и брать последний элемент используя функцию end(). Для копирования файлов пользуемся функцией copy().

<?php
    // общая функция загрузки картинки
    private function getPhoto($data)
    {
    	// берем последнюю картинку в массиве
        $file_id = $data[count($data) - 1]['file_id'];
        // получаем file_path
        $file_path = $this->getPhotoPath($file_id);
        // возвращаем результат загрузки фото
        return $this->copyPhoto($file_path);
    }

    // функция получения метонахождения файла
    private function getPhotoPath($file_id) {
    	// получаем объект File
        $array = json_decode($this->requestToTelegram(['file_id' => $file_id], "getFile"), TRUE);
        // возвращаем file_path
        return  $array['result']['file_path'];
    }

    // копируем фото к себе
    private function copyPhoto($file_path) {
    	// ссылка на файл в телеграме
        $file_from_tgrm = "https://api.telegram.org/file/bot".$this->botToken."/".$file_path;
        // достаем расширение файла
        $ext =  end(explode(".", $file_path));
        // назначаем свое имя здесь время_в_секундах.расширение_файла
        $name_our_new_file = time().".".$ext;
        return copy($file_from_tgrm, "img/".$name_our_new_file);
    }
?>

Подводим итог

Сохранить картинку через Телеграм бот очень просто. Методы Bot API позволяют это сделать быстро. Для сохранения других типов файлов с Телеграм алгоритм аналогичный. Скачать исходный код можно по этой ссылке


Комментарии

Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте бот @SiteAuthBot, нажмите кнопку Старт/Start. Следуйте инструкциям бота.


  • Хай
    - 20.02.2018 в 16:18
  • А можете подсказать чтобы бот вместе с успешной загрузкой выводил ещё и линк на загруженный файл?
    wo.rez 20.12.2018 в 17:24
    • Скинул решение в бот обратной связи
      iMakeBots 20.12.2018 в 17:39
  • Привет. Я писал код с нуля, не используя ничего. У вас тут есть функция requestToTelegram, не могу понять где ее можно взять, немного не понятно(
    Ильяс 07.04.2020 в 08:19
    • В архиве приложенном к статье есть файл index.php - в нем есть класс Bot в этом классе последний метод
          /** Отправляем запрос в Телеграмм
           * @param $data
           * @param string $type
           * @return mixed
           */
          private function requestToTelegram($data, $type)
          {
              $result = null;
              if (is_array($data)) {
                  $ch = curl_init();
                  curl_setopt($ch, CURLOPT_URL, $this->apiUrl . $this->botToken . '/' . $type);
                  curl_setopt($ch, CURLOPT_POST, count($data));
                  curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
                  curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
                  $result = curl_exec($ch);
                  curl_close($ch);
              }
              return $result;
          }
      iMakeBots 07.04.2020 в 08:27
  • можно готовый билд ?
    Winer 29.05.2020 в 09:22
    • В статье файл, это уже готовый билд
      iMakeBots 29.05.2020 в 11:03
  • Здраствуйте , а на ftp сервер загрузить можно и какой командой, чтоб успел загрузиться файл. Спасибо.
    Александр Alex 03.11.2020 в 18:01
  • А как переслать сразу файл в группу , не сохраняя на сервере, подскажите пожалуйста?
    Шардик 16.11.2020 в 18:03
    • и как отправить видеофайл / GIF? подстановка video вместо photo не решает задачу
      Шардик 16.11.2020 в 20:32
  • Эххх... Этот код бы перевести в Python... Кому под силу это сделать?
    Sergio64rus 01.02.2021 в 20:57
  • С чем может быть связано, что https://api.telegram.org/file/bot<token>/<file_path> стал отдавать код ошибки 404 спустя неделю работы? Новые файлы телеграм отправляет, выдает id файлов, но их по ссылкам на api.telegram нет
    Aleksandr Bigun 13.02.2021 в 21:50