~6 минут, Опубликовано 15.09.2024

Асинхронное скачивание файлов на Битрикс с помощью CURL

Асинхронное скачивание файлов на Битрикс с помощью CURL

Асинхронное скачивание файлов на Битрикс с помощью CURL

Введение

В современном веб-разработке, эффективная загрузка файлов является важным аспектом для поддержки стабильной и быстрой работы приложений. Особенно это актуально для проектов, которые работают с большим количеством медиафайлов, например, изображений или документов. В этой статье мы рассмотрим, как с помощью асинхронного скачивания файлов на платформе Битрикс можно значительно улучшить производительность вашего приложения, а также разберем тонкости использования cURL Multi для параллельной загрузки.

Зачем нужна асинхронная загрузка?

Загрузка файлов в синхронном режиме предполагает, что каждый файл загружается последовательно, что может существенно увеличивать время выполнения скрипта, особенно если объем загружаемых данных велик. Асинхронная загрузка позволяет запустить несколько запросов параллельно, что значительно ускоряет процесс.

На платформе Битрикс асинхронное скачивание файлов с использованием cURL Multi позволяет:

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

Принцип работы асинхронного скачивания с cURL Multi

cURL — это библиотека для передачи данных с использованием различных протоколов, таких как HTTP, FTP, SMTP и других. В данном случае нас интересует работа с cURL Multi, который позволяет управлять сразу несколькими запросами одновременно.

Читайте также  Как добавить поиск по свойствам в bitrix:catalog.search

Особенности cURL Multi:

  1. Асинхронность — запросы выполняются параллельно, и вам не нужно дожидаться завершения одного запроса для начала следующего.
  2. Эффективное управление ресурсами — использование мультиплексирования запросов снижает задержки и позволяет более эффективно использовать системные ресурсы.
  3. Управление дескрипторами — cURL Multi работает с несколькими дескрипторами запросов одновременно и поддерживает контроль за их выполнением.

Пример кода

Давайте рассмотрим конкретную реализацию на примере кода:

protected function saveFiles(array $urls): array
    {
        // Массив для хранения дескрипторов cURL
        $multiCurl = [];
        $mh = curl_multi_init();

        // Инициализируем cURL запросы
        foreach ($urls as $i => $url) {
            $multiCurl[$i] = curl_init();
            curl_setopt($multiCurl[$i], CURLOPT_URL, $url);
            curl_setopt($multiCurl[$i], CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($multiCurl[$i], CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($multiCurl[$i], CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($multiCurl[$i], CURLOPT_SSL_VERIFYHOST, false);
            curl_multi_add_handle($mh, $multiCurl[$i]);
        }

        // Выполняем все запросы
        $running = null;
        do {
            curl_multi_exec($mh, $running);
            curl_multi_select($mh);
        } while ($running > 0);

        $files = [];

        // Обрабатываем результаты
        foreach ($multiCurl as $i => $ch) {
            $response = curl_multi_getcontent($ch);

            if(!$response){
                continue;
            }

            $url = $urls[$i];
            $pathInfo = pathinfo(parse_url($url, PHP_URL_PATH));
            $extension = $pathInfo['extension'] ?? null;

            if(is_null($extension)){
                continue;
            }

            $tmpDirectory = \CTempFile::GetDirectoryName();
            $tmpName =  $tmpDirectory.$pathInfo['basename'];

            \Bitrix\Main\IO\Directory::createDirectory($tmpDirectory);

            $res = file_put_contents($tmpName, $response);

            if(!$res){
                continue;
            }

            $fileSize = filesize($tmpName);
            $fileType = mime_content_type($tmpName);

            $files[] = [
                'name' => $pathInfo['basename'],
                'size' => $fileSize,
                'tmp_name' => $tmpName,
                'type' => $fileType
            ];


            // Удаляем дескриптор cURL
            curl_multi_remove_handle($mh, $ch);
            curl_close($ch);
        }

        // Закрываем дескриптор cURL
        curl_multi_close($mh);

        return $files;
    }

 

Детали работы данного метода

1. Инициализация cURL дескрипторов

Для каждого URL, который мы передаем в метод, создается cURL-дескриптор, который управляет запросом к серверу. Параметры, передаваемые через curl_setopt, позволяют задать такие настройки, как:

  • CURLOPT_RETURNTRANSFER — возвращать результат в виде строки.
  • CURLOPT_FOLLOWLOCATION — следовать за редиректами.
  • CURLOPT_SSL_VERIFYPEER и CURLOPT_SSL_VERIFYHOST — отключение валидации SSL, что ускоряет процесс, но используется только в безопасных окружениях.

2. Запуск параллельного выполнения запросов

Мы используем curl_multi_exec для запуска всех запросов одновременно. Этот цикл работает до тех пор, пока все запросы не будут завершены. Такой подход позволяет значительно ускорить процесс загрузки по сравнению с последовательными запросами.

Читайте также  Как установить 404-ошибку на странице Битрикс

3. Получение ответа и сохранение файлов

После завершения каждого запроса мы получаем контент с помощью curl_multi_getcontent. Если ответ получен корректно, он сохраняется в файловую систему на временное хранилище с помощью file_put_contents.

4. Работа с временными файлами

Файлы сохраняются во временные директории, создаваемые через \CTempFile::GetDirectoryName(). Эта функция предоставляет временную директорию для файлов, которую можно легко очистить после завершения работы.

Тонкости и особенности использования cURL Multi на Битрикс

1. Ограничение на количество одновременных потоков

Стоит отметить, что серверные ресурсы могут ограничивать количество одновременных соединений. Если у вас много URL для загрузки, стоит ограничить число потоков (дескрипторов cURL), чтобы избежать перегрузки сервера и ошибок выполнения. Можно использовать технику “батчей” — запускать загрузку файлами группами, например, по 10-20 файлов за раз.

2. Работа с типами файлов

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

3. Безопасность

При работе с файлами через интернет стоит учитывать безопасность. Отключение проверки SSL, как показано в примере, возможно только в контролируемых средах, например, при локальной разработке или на внутренних серверах. На боевых серверах лучше оставить включенной валидацию SSL для предотвращения потенциальных атак.

4. Очистка ресурсов

Важно не забывать освобождать дескрипторы cURL после их использования с помощью curl_multi_remove_handle и закрывать их через curl_close. Это необходимо для предотвращения утечек памяти и стабильной работы приложения.

Тестирование и сравнение скорости

В процессе тестирования мы сравнили стандартный метод синхронного скачивания файлов через CFile::MakeFileArray с нашим асинхронным подходом на базе cURL.

Читайте также  Как авторизоваться под другого пользователя в Битрикс

Для теста использовались 17 изображений. Ниже представлены результаты времени выполнения для обоих подходов:

  • Синхронный метод через CFile::MakeFileArray: Среднее время скачивания всех 17 изображений составило 3.5-4 секунды.
  • Асинхронное скачивание через cURL (multi-cURL): Время выполнения не превышало 0.5 секунд для тех же 17 изображений.

Прирост производительности:

Чтобы оценить прирост производительности, мы можем рассчитать ускорение:

  1. Синхронный подход: 3.5-4 секунд.
  2. Асинхронный подход: 0.5 секунд.

Среднее время синхронного подхода составляет 3.75 секунд. Для асинхронного подхода это 0.5 секунд.

Теперь посчитаем прирост:

Таким образом, асинхронное скачивание ускоряет процесс в 7.5 раз по сравнению со стандартным синхронным подходом.

Пример:

Допустим, у вас есть страница с каталогом товаров, на которой требуется загрузить 50 изображений для рендеринга. Используя стандартный подход, загрузка займет около 11-12 секунд, что негативно скажется на пользовательском опыте. Однако с применением асинхронного скачивания это время сократится до 1.5-2 секунд, что делает загрузку значительно быстрее и улучшает производительность системы.

Заключение

Асинхронное скачивание файлов с использованием cURL Multi — это мощный инструмент для повышения производительности на веб-платформе Битрикс. Правильная настройка и использование этого механизма позволяет значительно ускорить процесс загрузки файлов, особенно при работе с большим количеством медиафайлов. Важно помнить о тонкостях управления ресурсами, безопасностью, а также корректной обработке различных типов данных.


Категории: Bitrix PHP