Часто разработчики 1С сталкиваются с ситуацией, когда запрос, идеально работающий в Postman или через curl, выдает ошибку при попытке реализовать его в коде 1С. Особенно это касается передачи изображений или файлов через формат multipart/form-data. В данной статье мы разберем, почему возникают ошибки распознавания расширения файла, как правильно формировать тело запроса и почему стоит отказаться от использования COM-объекта WinHttp.WinHttpRequest.5.1 в пользу встроенных средств платформы.
Разберем типичную ситуацию: автор пытается отправить изображение в формате base64 для распознавания текста. API возвращает ошибку, утверждая, что не может распознать расширение или файл пуст. Основная причина здесь кроется не в логике API, а в физической структуре HTTP-пакета, который формирует 1С.
Проанализируем ключевые факторы, влияющие на успех запроса:
multipart данных должны состоять из последовательности "Возврат каретки" и "Перевод строки" (\r\n). В 1С при использовании многострочной строки через вертикальную черту | используется только символ ПС (\n). Большинство серверов (включая OCR.space) не смогут корректно распарсить границы (boundary), если они разделены не по стандарту.base64Image недостаточно просто получить строку. API часто ожидает Data URI заголовок, например: data:image/jpeg;base64,.... Без него сервер может не понять тип передаваемого контента.WinHttp происходит неявная конвертация в Unicode или ANSI. Если в теле запроса присутствуют бинарные части, они могут быть повреждены.Рассмотрим, как правильно собрать тело запроса multipart/form-data. Нам необходимо явно использовать Символы.ВК + Символы.ПС для каждого переноса строки. Выясним, как должна выглядеть структура одной части запроса.
Разделитель = "----WebKitFormBoundary7MA4YWxkTrZu0gW";
ВКПС = Символы.ВК + Символы.ПС;
ТелоЗапроса = "--" + Разделитель + ВКПС;
ТелоЗапроса = ТелоЗапроса + "Content-Disposition: form-data; name=""base64Image""" + ВКПС + ВКПС;
ТелоЗапроса = ТелоЗапроса + "data:image/jpeg;base64," + СтрокаBase64 + ВКПС;
ТелоЗапроса = ТелоЗапроса + "--" + Разделитель + ВКПС;
ТелоЗапроса = ТелоЗапроса + "Content-Disposition: form-data; name=""language""" + ВКПС + ВКПС;
ТелоЗапроса = ТелоЗапроса + "eng" + ВКПС;
ТелоЗапроса = ТелоЗапроса + "--" + Разделитель + "--" + ВКПС;
Важный нюанс: Обратите внимание на финальный разделитель. Он должен заканчиваться двумя дефисами: --Разделитель--. Это сигнализирует серверу об окончании передачи данных.
Использование WinHttp.WinHttpRequest.5.1 в современной 1С является избыточным и потенциально опасным. Рассмотрим преимущества использования встроенных объектов HTTPСоединение и HTTPЗапрос. Они позволяют корректно работать с кодировками и автоматически устанавливать важные заголовки, такие как Content-Length.
Проанализируем пример кода, который реализует отправку данных через встроенные механизмы:
// Настройка соединения
Сервер = "api.ocr.space";
Соединение = Новый HTTPСоединение(Сервер, 443, , , , , Новый ЗащищенноеСоединениеOpenSSL());
// Формирование заголовков
ЗаголовокHTTP = Новый Соответствие;
ЗаголовокHTTP.Вставить("apikey", "ВашКлючAPI");
// Важно: boundary в заголовке должен совпадать с тем, что в теле
ЗаголовокHTTP.Вставить("Content-Type", "multipart/form-data; boundary=" + Разделитель);
// Создание запроса
Запрос = Новый HTTPЗапрос("/parse/image", ЗаголовокHTTP);
// Преобразование строки тела в двоичные данные (UTF-8 без BOM)
ДанныеТела = ПолучитьДвоичныеДанныеИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, Ложь);
Запрос.УстановитьТелоИзДвоичныхДанных(ДанныеТела);
// Отправка и получение ответа
Ответ = Соединение.ОтправитьДляОбъекта(Запрос);
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку();
Если изображение очень большое, формирование огромной строки в памяти может привести к ошибке Недостаточно памяти. Разберем, как использовать ПотокВПамяти и ЗаписьДанных для более эффективной работы. Этот метод позволяет записывать данные в поток порциями.
Поток = Новый ПотокВПамяти();
ЗаписьДанных = Новый ЗаписьДанных(Поток, КодировкаТекста.UTF8);
ЗаписьДанных.ЗаписатьСтроку("--" + Разделитель);
ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""language""");
ЗаписьДанных.ЗаписатьСтроку(""); // Пустая строка между заголовком и данными
ЗаписьДанных.ЗаписатьСтроку("eng");
// Повторяем для всех полей...
ЗаписьДанных.Закрыть();
РезультатБинарный = Поток.ЗакрытьИПолучитьДвоичныеДанные();
Запрос.УстановитьТелоИзДвоичныхДанных(РезультатБинарный);
Использование ЗаписьДанных с параметром кодировки гарантирует, что все символы будут корректно преобразованы в UTF-8, а переходы строк будут соответствовать стандарту.
Если запрос все равно возвращает ошибку, проанализируем следующие моменты:
УстановитьТелоИзДвоичныхДанных. Платформа 1С вычислит его автоматически. Ошибка в 1 байт приведет к тому, что сервер отклонит запрос.https://api.ocr.space обязательно использование объекта ЗащищенноеСоединениеOpenSSL() в конструкторе HTTPСоединение.true/false в multipart-запросах передаются как обычный текст.Мы выяснили, что ключ к успешному POST-запросу из 1С к внешним сервисам — это строгое соблюдение структуры протокола HTTP и использование современных инструментов платформы. Отказ от COMОбъект в пользу HTTPЗапрос не только делает код более читаемым и кроссплатформенным (работает в Linux-версиях сервера 1С), но и избавляет от проблем с кодировками и расчетом длины контента.