При интеграции 1С с внешними веб-сервисами, интернет-магазинами (например, на платформе 1C-Битрикс) или облачными хранилищами разработчики часто сталкиваются с задачей отправки файлов на сервер по протоколу HTTP/HTTPS. Начинающие специалисты нередко пытаются прочитать весь файл с диска в строковую переменную или двоичные данные, после чего сталкиваются с вопросом: как именно прикрепить файл к запросу и какой метод соединения выбрать?
Разберем по шагам, как правильно передавать файлы на веб-сервер, почему не стоит загружать объемные файлы целиком в оперативную память и как учесть особенности интеграции.
Проанализируем типовую ситуацию. Разработчик создает объект HTTPСоединение, формирует HTTPЗапрос и хочет отправить файл, лежащий на локальном диске (например, выгрузку каталога в формате XML размером 10–30 МБ). При этом в документации к объекту HTTPЗапрос встречаются методы УстановитьТелоИзСтроки(), УстановитьТелоИзДвоичныхДанных(), УстановитьИмяФайлаТела() и УстановитьТелоИзПотока(). Возникает вопрос: какой способ предпочесть и где указать имя исходного файла на диске?
Если прочитать файл размером 30 МБ в строку через ЧтениеТекста или загрузить в память как ДвоичныеДанные, платформа выделит под этот объект значительный объем оперативной памяти в сеансе. При многопользовательской работе или обработке гигантских файлов это приводит к падению производительности и ошибкам нехватки памяти.
В платформе 1С предусмотрен специализированный метод УстановитьИмяФайлаТела() у объекта HTTPЗапрос. Он принимает путь к файлу на диске в виде обычной строки. Платформа самостоятельно связывает этот файл с телом исходящего запроса и передает его потоком без полной вычитки в память.
Посмотрим на практический пример правильного формирования запроса:
Сервер = "sait.by";
АдресРесурса = "/bitrix/admin/1c_exchange.php?mode=file&filename=import.xml";
ИмяФайлаОтправки = "C:\Exchange\import.xml";
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса, Заголовки);
HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаОтправки);
SSL = Новый ЗащищенноеСоединениеOpenSSL;
HTTPСоединение = Новый HTTPСоединение(Сервер, 443, "Логин", "Пароль",,, SSL);
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
Выясним причину, почему в примерах кода встречаются разные методы объекта HTTPСоединение:
1c_exchange.php, веб-сервисы сбора аналитики или формы загрузки документов.Если веб-сервер или документация API явно требуют отправки формы или передачи данных обработчику, следует вызывать именно ОтправитьДляОбработки().
Рассмотрим подробнее другие варианты передачи содержимого, которые могут пригодиться в специфических сценариях:
УстановитьТелоИзПотока): если файл формируется динамически или передается через поток данных, можно использовать ФайловыйПоток с режимом чтения. Это также исключает чрезмерное потребление памяти.УстановитьТелоИзСтроки() и УстановитьТелоИзДвоичныхДанных() подходят только для небольших фрагментов данных (JSON-сообщения, маленькие XML-пакеты до пары мегабайт). Использовать их для файлов от 10 МБ и выше не рекомендуется.HTTPСоединение.ОтправитьДляОбработки() позволяет указать имя выходного файла в качестве второго параметра. В этом случае тело ответа сервера сразу запишется на диск, минуя память сеанса.Разберем особенности, которые критически важны при интеграции с интернет-магазинами на базе 1C-Битрикс:
1c_exchange.php не принимает файл при прямом одиночном запросе. Сначала выполняется шаг проверки авторизации (mode=checkauth). Сервер возвращает имя и значение сессионной куки (или заголовок Set-Cookie). Полученный идентификатор необходимо передавать в заголовке Cookie на всех последующих шагах, включая передачу файла (mode=file).200 OK говорит лишь о том, что веб-сервер передал запрос интерпретатору PHP. Успешность самого действия возвращается в первой строке тела ответа: success, progress или failure. Обязательно анализируйте результат через HTTPОтвет.ПолучитьТелоКакСтроку().filename) содержит кириллицу или специальные знаки, строку необходимо преобразовать с помощью функции КодироватьСтроку(ИмяФайла, СпособКодированияСтроки.КодировкаURL).Таймаут в конструкторе HTTPСоединение до 120–300 секунд.ЗаписьZipФайла и передавать уже архив с расширением .zip.