Как передать строку на сервер через POST-запрос в 1С (имитация загрузки файла)

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

При интеграции 1С с веб-сервисами часто возникает задача передать текстовые данные или файл через POST-запрос. Одной из наиболее распространенных проблем является попытка отправить данные как простую строку, в то время как принимающий сервер (например, скрипт на PHP) ожидает данные в формате загрузки файла. В этой статье мы подробно разберем, как правильно сформировать такой запрос, почему стандартные методы могут не работать и как использовать инструменты отладки для достижения результата.

В чем заключается основная проблема

Рассмотрим стандартную ситуацию: вы используете HTTPЗапрос и метод УстановитьТелоИзСтроки(), устанавливая заголовок Content-Type: application/x-www-form-urlencoded. Если на стороне сервера стоит скрипт, обрабатывающий массив $_FILES, такой запрос вернет ошибку (например, "File uploading failed"), так как данные попадут в массив $_POST, а не в структуру файлов.

Для корректной передачи "строки как файла" нам необходимо имитировать работу команды curl -F, которая принудительно использует формат multipart/form-data. Этот формат требует специальной разметки тела запроса с использованием уникальных разделителей (границ).

Шаг 1. Анализ запроса с помощью инструментов отладки

Прежде чем приступать к написанию кода в 1С, проанализируем, как именно передаются данные через работающие инструменты, такие как curl. Разберем по шагам, как настроить сравнение запросов:

  1. Запустим инструмент Fiddler (или любой другой сниффер трафика).
  2. Выполним команду отправки файла через curl, пробросив трафик через прокси Fiddler, чтобы увидеть структуру пакета. Пример команды в консоли: curl -F "pp=@masageB.txt" -x 127.0.0.1:8888 -k http://your-server.ru/addfile.php
  3. В Fiddler проанализируем вкладку Inspectors -> Raw. Мы увидим, что запрос содержит заголовок boundary (граница) и специфическую структуру тела, где указаны Content-Disposition, name и filename.

Наша задача в 1С — в точности воспроизвести эту структуру.

Шаг 2. Формирование структуры Multipart/Form-Data вручную

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

Проанализируем ключевой момент: использование правильных символов перевода строки. Для веб-серверов критически важно использовать комбинацию Символы.ВК + Символы.ПС (CRLF).

Рассмотрим пример кода для формирования тела запроса:


&НаСервере
Функция СформироватьТелоЗапроса(ТекстФайла, ИмяФайла, Граница)
    
    Разделитель = "--" + Граница;
    ПереносСтроки = Символы.ВК + Символы.ПС;
    
    Тело = Разделитель + ПереносСтроки;
    Тело = Тело + "Content-Disposition: form-data; name=""pp""; filename=""" + ИмяФайла + """" + ПереносСтроки;
    Тело = Тело + "Content-Type: text/plain" + ПереносСтроки + ПереносСтроки; // Двойной перенос перед текстом
    Тело = Тело + ТекстФайла + ПереносСтроки;
    Тело = Тело + Разделитель + "--" + ПереносСтроки; // Финальный разделитель с двумя дефисами в конце
    
    Возврат Тело;
КонецФункции

Шаг 3. Реализация отправки через HTTPСоединение

Теперь соберем все воедино в основной функции отправки. Обратите внимание на установку заголовков. Выясним причину, по которой сервер может отклонять запросы от 1С: иногда стандартный заголовок User-Agent (который по умолчанию содержит "1C+Enterprise") блокируется брандмауэрами или настройками веб-сервера.

Рассмотрим реализацию метода отправки:


&НаСервере
Процедура ОтправитьФайлНаСервер()
    
    Сервер = "10.255.1.232";
    Ресурс = "/~andy/tsd/addfile.php";
    ТекстДляПередачи = "Это содержимое нашего будущего файла";
    ИмяФайлаНаСервере = "test_message.txt";
    
    // Генерируем уникальную границу
    Граница = "----" + СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
    
    Заголовки = Новый Соответствие;
    // Указываем тип контента и границу
    Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Граница);
    // Маскируем 1С под обычный браузер (важно!)
    Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
    
    HTTPСоединение = Новый HTTPСоединение(Сервер);
    HTTPЗапрос = Новый HTTPЗапрос(Ресурс, Заголовки);
    
    // Формируем тело
    СтрокаТела = СформироватьТелоЗапроса(ТекстДляПередачи, ИмяФайлаНаСервере, Граница);
    HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаТела, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    
    Попытка
        HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
        Сообщить("Код состояния: " + HTTPОтвет.КодСостояния);
        Сообщить("Ответ сервера: " + HTTPОтвет.ПолучитьТелоКакСтроку());
    Исключение
        Сообщить("Ошибка связи: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Важные нюансы при работе с HTTP в 1С

Разберем подробнее тонкости, которые могут повлиять на успешный результат:

  1. Кодировка и BOM: При использовании УстановитьТелоИзСтроки() 1С может добавить метку BOM (Byte Order Mark) в начало данных. Некоторые PHP-скрипты некорректно воспринимают BOM при сохранении файла. Рекомендуется использовать параметр ИспользованиеByteOrderMark.НеИспользовать.
  2. Разделители строк: В среде Windows 1С использует Символы.ПС, но протокол HTTP требует именно CRLF (ВК + ПС). Если ваш сервер работает на Linux (Apache/Nginx), он может быть чувствителен к отсутствию Символы.ВК.
  3. Использование Двоичных Данных: Если передаваемая строка содержит сложные символы или вы планируете передавать настоящие файлы (картинки, PDF), лучше собирать тело запроса через ЗаписьДанных в буфер, чтобы избежать проблем с кодировками строк.
  4. Мобильная платформа: Описанный выше метод формирования multipart/form-data вручную — единственный надежный способ для мобильной платформы 1С, так как там недоступны внешние компоненты или сложные COM-объекты типа WinHttp.WinHttpRequest.

Итоги

Мы проанализировали ситуацию, когда обычная отправка строки не воспринимается сервером как загрузка файла. Для решения проблемы мы применили формат multipart/form-data, вручную сконструировали тело запроса с соблюдением стандартов boundary и CRLF, а также подменили User-Agent для обхода возможных ограничений сервера. Этот подход является универсальным и работает в любых конфигурациях 1С на платформе 8.3.

← На главную