Как получить и сохранить файл через API в 1С:Предприятии

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В современной разработке на платформе 1С:Предприятие часто возникает задача интеграции с внешними сервисами. Одной из самых распространенных подзадач является получение файлов (изображений, PDF-документов, архивов) через API. Часто начинающие разработчики сталкиваются с ситуацией, когда вместо привычного файла в ответе приходят «странные символы». Проанализируем, как правильно обработать поток данных и превратить его в полноценный файл на диске. Если же требуется автоматизировать получение подобных данных от внешних поставщиков без программирования, можно настроить готовый сбор прайс-листов и файлов с почты, FTP, HTTP с последующей обработкой.

Разбор ситуации: почему приходят «иероглифы»

Когда мы отправляем запрос к API, которое предназначено для скачивания файла, сервер не присылает файл в привычном понимании (как иконку на рабочем столе). Он передает содержимое файла в виде потока байтов. Если попытаться вывести этот ответ в текстовое поле или через команду Сообщить, мы увидим содержимое двоичного файла, интерпретированное как текст. Например, заголовок JFIF в начале ответа однозначно указывает на то, что перед нами изображение в формате JPEG.

Рассмотрим пошагово, как правильно реализовать получение и сохранение таких данных, используя встроенные механизмы 1С.

Базовый алгоритм получения файла через HTTPЗапрос

Для работы с HTTP-сервисами в 1С используются объекты HTTPСоединение и HTTPЗапрос. Разберем стандартный пример кода, который позволяет загрузить картинку по прямой ссылке.


// Определим параметры подключения
Сервер = "thumb7.shutterstock.com";
ПутьКРесурсу = "/display_pic_with_logo/1014806/270790184/stock-photo-summer-holidays-background-sea-background-270790184.jpg";

// Создаем соединение
Соединение = Новый HTTPСоединение(Сервер);

// Формируем запрос
Запрос = Новый HTTPЗапрос(ПутьКРесурсу);

// Отправляем запрос и получаем ответ
Результат = Соединение.Получить(Запрос);

Если Результат.КодСостояния = 200 Тогда
    // Получаем данные в виде двоичного потока
    ДвоичныеДанныеФайла = Результат.ПолучитьТелоКакДвоичныеДанные();
    
    // Определяем путь сохранения
    ПутьНаДиске = "C:\temp\downloaded_image.jpg";
    
    // Записываем данные в файл
    ДвоичныеДанныеФайла.Записать(ПутьНаДиске);
    Сообщить("Файл успешно сохранен: " + ПутьНаДиске);
Иначе
    Сообщить("Ошибка при загрузке. Код состояния: " + Результат.КодСостояния);
КонецЕсли;

Профессиональный подход: оптимизация и нюансы

Хотя вышеприведенный код работоспособен, в реальных проектах необходимо учитывать несколько критически важных нюансов, которые делают решение отказоустойчивым и эффективным.

1. Работа с большими файлами и экономия памяти

Метод ПолучитьТелоКакДвоичныеДанные() загружает весь файл целиком в оперативную память сервера или клиента. Если вы скачиваете видеофайл или тяжелый PDF размером 500 МБ, это может привести к падению рабочего процесса 1С. Выясним, как этого избежать.

Для оптимизации рекомендуется использовать второй параметр метода Получить(). В этом случае 1С будет записывать данные напрямую из сетевого потока на диск, минуя оперативную память.


ИмяФайлаПриемника = ПолучитьИмяВременногоФайла("jpg");
Результат = Соединение.Получить(Запрос, ИмяФайлаПриемника);

// Теперь файл уже лежит на диске по пути ИмяФайлаПриемника
// Нам не нужно вызывать ПолучитьТелоКакДвоичныеДанные()

2. Динамическое определение имени файла из заголовков

Часто API не содержит расширения файла прямо в URL (например, запрос идет к методу /api/v1/get_document?id=123). В таких случаях сервер передает имя файла в HTTP-заголовке Content-Disposition. Проанализируем, как извлечь оригинальное имя файла.


Заголовки = Результат.Заголовки;
ContentDisposition = Заголовки.Получить("Content-Disposition");

// Обычно строка выглядит так: attachment; filename="report_2023.pdf"
Если ContentDisposition <> Неопределено Тогда
    ПозицияИмени = Найти(ContentDisposition, "filename=");
    Если ПозицияИмени > 0 Тогда
        ОригинальноеИмя = Сред(ContentDisposition, ПозицияИмени + 9);
        ОригинальноеИмя = СтрЗаменить(ОригинальноеИмя, """", ""); // Убираем кавычки
    КонецЕсли;
КонецЕсли;

3. Безопасное соединение (HTTPS) и SSL

Современные API практически никогда не работают через незащищенный протокол HTTP (порт 80). Для работы с HTTPS необходимо использовать объект ЗащищенноеСоединениеOpenSSL. Без этого параметра вызов HTTPСоединение к защищенному ресурсу вернет ошибку.


// Инициализируем защищенное соединение
Защита = Новый ЗащищенноеСоединениеOpenSSL();
// Указываем порт 443 для HTTPS
Соединение = Новый HTTPСоединение("api.myservice.com", 443, , , , , Защита);

4. Использование временных файлов и права доступа

Никогда не используйте жестко прописанные пути вроде C:\temp\ в серверном коде. У службы, под которой запущен сервер 1С, может не быть прав на запись в корень диска C:. Правильный подход — использование системной функции ПолучитьИмяВременногоФайла(). Это гарантирует уникальность имени и наличие прав доступа.

Рассмотрим правильный цикл работы с временным файлом:

  1. Генерируем уникальный путь во временной директории системы.
  2. Скачиваем данные по этому адресу.
  3. Обрабатываем файл (например, прикрепляем к документу в базе).
  4. Удаляем временный файл с помощью команды УдалитьФайлы(), чтобы не засорять сервер.

5. Обработка ошибок и кодов состояния

Важно помнить, что даже если запрос технически «прошел», это не значит, что скачался именно файл. Если API вернуло ошибку 404 (Не найдено) или 401 (Не авторизован), в теле ответа вместо картинки может прийти JSON с текстом ошибки. Попытка сохранить этот текст как .jpg создаст битый файл, который не откроется. Для отладки HTTP-запросов и проверки ответов сервера пригодится инструмент для тестирования REST API в 1С.

Всегда проверяйте код состояния перед сохранением:

Итоговый пример надежного кода

Сведем все полученные знания в одну универсальную функцию для скачивания файлов.


Функция СкачатьФайлИзAPI(УРЛ_Сервера, ПутьНаСервере, Токен) Экспорт
    
    Защита = Новый ЗащищенноеСоединениеOpenSSL();
    Соединение = Новый HTTPСоединение(УРЛ_Сервера, 443, , , , 30, Защита);
    
    Запрос = Новый HTTPЗапрос(ПутьНаСервере);
    Запрос.Заголовки.Вставить("Authorization", "Bearer " + Токен);
    
    ПутьВременный = ПолучитьИмяВременногоФайла();
    
    Попытка
        Ответ = Соединение.Получить(Запрос, ПутьВременный);
        
        Если Ответ.КодСостояния = 200 Тогда
            Возврат ПутьВременный;
        Иначе
            // Если ошибка, удалим пустой/битый файл
            УдалитьФайлы(ПутьВременный);
            ЗаписьЖурналаРегистрации("API", УровеньЖурналаРегистрации.Ошибка, , , 
                "Ошибка загрузки. Код: " + Ответ.КодСостояния);
            Возврат Неопределено;
        КонецЕсли;
    Исключение
        ЗаписьЖурналаРегистрации("API", УровеньЖурналаРегистрации.Ошибка, , , 
            "Критическая ошибка связи: " + ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
    
КонецФункции

Используя данный подход, мы обеспечиваем стабильную работу системы, корректную обработку исключений и оптимальное использование ресурсов сервера при работе с любыми типами файлов через внешние API.

← На главную