Как отправить изображения из 1С на сайт через POST-запрос?

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

Интеграция 1С с веб-сайтами и сторонними сервисами часто требует передачи двоичных данных, в частности — изображений. В протоколе HTTP для передачи файлов стандартно используется формат multipart/form-data. В данной статье мы подробно разберем, как правильно сформировать тело такого запроса, какие ошибки часто допускают разработчики и как сделать код более современным и надежным.

Разбор механизма multipart/form-data

Когда мы отправляем форму с файлом через браузер, данные упаковываются в специальный формат, где разные части (поля текста и файлы) отделяются друг от друга уникальной строкой-разделителем, называемой Boundary. Наша задача в 1С — вручную или с помощью встроенных объектов собрать такое «тело» запроса.

Рассмотрим классический подход, основанный на объединении текстовых и двоичных файлов. Этот метод часто встречается в старых обработках, но он до сих пор работоспособен и наглядно показывает структуру пакета.

Типичный алгоритм формирования запроса выглядит следующим образом:

  1. Создание уникального разделителя Boundary.
  2. Подготовка текстового заголовка для файла (имя поля, имя файла, тип контента).
  3. Подготовка самого двоичного файла.
  4. Подготовка текстового завершения (финальный разделитель).
  5. Объединение всех частей в один файл и его отправка.

Реализация через объединение файлов

Проанализируем пример кода, который формирует структуру запроса. Обратите внимание на формирование заголовков внутри тела.


// 1. Инициализация параметров
ИмяФайлаДляЗагрузки = "C:\Upload\picture.jpg";  
Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", ""); 
ИмяФайлаОтправки = КаталогВременныхФайлов() + "post_body.txt"; 

// 2. Формируем начало запроса
ИмяФайлаНачало = ПолучитьИмяВременногоФайла("txt"); 
ФайлНачало = Новый ЗаписьТекста(ИмяФайлаНачало, КодировкаТекста.ANSI); 
ФайлНачало.ЗаписатьСтроку("--" + Boundary); 
ФайлНачало.ЗаписатьСтроку("Content-Disposition: form-data; name=""file1""; filename=""image.jpg"""); 
// ВАЖНО: Правильный MIME-тип для картинок
ФайлНачало.ЗаписатьСтроку("Content-Type: image/jpeg"); 
ФайлНачало.ЗаписатьСтроку(""); // Пустая строка перед двоичными данными
ФайлНачало.Закрыть(); 

// 3. Формируем конец запроса
ИмяФайлаКонец = ПолучитьИмяВременногоФайла("txt"); 
ФайлКонец = Новый ЗаписьТекста(ИмяФайлаКонец, КодировкаТекста.ANSI); 
ФайлКонец.ЗаписатьСтроку("");
ФайлКонец.ЗаписатьСтроку("--" + Boundary + "--"); 
ФайлКонец.Закрыть(); 

// 4. Объединяем части
МассивФайлов = Новый Массив; 
МассивФайлов.Добавить(ИмяФайлаНачало); 
МассивФайлов.Добавить(ИмяФайлаДляЗагрузки); 
МассивФайлов.Добавить(ИмяФайлаКонец); 
ОбъединитьФайлы(МассивФайлов, ИмяФайлаОтправки);

В этом примере критически важным моментом является указание Content-Type. Если сервер ожидает изображение, а вы передаете application/x-zip-compressed или application/octet-stream, сервер может отклонить запрос с ошибкой «Неверный тип файла».

Распространенные ошибки и способы их решения

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

1. Ошибка в окончаниях строк (CRLF)

Согласно спецификации HTTP, строки в multipart должны разделяться парой символов ВК + ПС (CR+LF). В 1С метод ЗаписатьСтроку() по умолчанию может использовать только ПС. Если сервер строгий (например, на базе Nginx), он не увидит границы. Рекомендуется явно указывать символы:

ФайлНачало.Записать("--" + Boundary + Символы.ВК + Символы.ПС);

2. Кодировка текстовых фрагментов

Использование КодировкаТекста.ANSI допустимо только для английских имен файлов. Если в filename или значениях полей формы присутствует кириллица, необходимо использовать КодировкаТекста.UTF8, причем желательно без метки BOM, так как лишние байты в начале файла могут повредить структуру запроса.

3. Опечатки в заголовках

Будьте внимательны при ручной установке заголовков HTTPЗапрос. Например, ошибка в слове Content-Length (написание Content-Lenght) приведет к тому, что сервер не поймет размер передаваемых данных. Однако стоит помнить, что при использовании метода УстановитьИмяФайлаТела(), платформа 1С 8.3 самостоятельно вычисляет размер и добавляет этот заголовок.

Современный подход: использование потоков данных

Начиная с версии 1С 8.3.6, мы можем отказаться от создания множества временных файлов на диске и манипулировать данными прямо в оперативной памяти с помощью объектов Поток и ЗаписьДанных. Это значительно ускоряет работу и повышает надежность кода.

Разберем пример реализации через ПотокВПамяти:


Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", ""); 
ПотокТела = Новый ПотокВПамяти();
ЗаписьДанных = Новый ЗаписьДанных(ПотокТела, КодировкаТекста.UTF8);

// Записываем начало
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""picture.jpg""");
ЗаписьДанных.ЗаписатьСтроку("Content-Type: image/jpeg");
ЗаписьДанных.ЗаписатьСтроку(""); // Разделитель между заголовком и данными

// Записываем саму картинку
КартинкаДвоичные = Новый ДвоичныеДанные("C:\data\img.jpg");
ЗаписьДанных.Записать(КартинкаДвоичные);

// Записываем финал
ЗаписьДанных.ЗаписатьСтроку("");
ЗаписьДанных.ЗаписатьСтроку("--" + Boundary + "--");
ЗаписьДанных.Закрыть();

// Получаем итоговые данные для запроса
ДанныеДляОтправки = ПотокТела.ЗакрытьИПолучитьДвоичныеДанные();

HTTPЗапрос = Новый HTTPЗапрос("/api/upload");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);
HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ДанныеДляОтправки);

HTTPСоединение = Новый HTTPСоединение("mysite.com");
Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);

Как проверить, что уходит на сервер?

Если код в 1С кажется верным, но сайт все равно выдает ошибку, проанализируем ситуацию с помощью инструментов отладки (Proxy-серверов), таких как Fiddler или Charles. Сравните запрос, который формирует Postman (если в нем загрузка работает), с запросом из 1С. Основное внимание уделите:

Выяснив причину через сравнение «сырых» HTTP-пакетов, вы сможете легко поправить код формирования тела запроса в 1С. Помните, что веб-сервер крайне чувствителен к структуре multipart/form-data, и даже один пропущенный символ перевода строки может сделать весь файл нечитаемым для принимающей стороны.

← На главную