QR-код в 1С 8.3 на Linux: HTTPСоединение и временное хранилище вместо COM
QР-код в 1С 8.3 на сервере под Linux я получаю без СОМ-объектов: штатное НТТРСоединение, запись PNG из тела ответа и адрес во временном хранилище для поля картинки на форме или для печати. Если вы переносите типовой пример с Windows, где HTTP и бинарный файл делают через Microsoft.XMLHTTP и ADODB.Stream, на Linux этот путь обрывается. Ниже разложу замену по шагам: те же данные в QR, другой транспорт и другой способ доставить картинку в интерфейс.
Разберите задачу: QR в 1С на Linux без COM
На форме документа или в печатной форме нужна картинка QR с текстом: номер заказа, контрагент, иногда сумма или ссылка. Платформа 1С:Предприятие 8.3.24 (пример; у себя сверьте релиз) на Windows часто решает это через COM: ActiveX отправляет GET, responseBody пишут в файл, из файла создают объект Картинка. На Linux у сервера приложений СОМ-объекты недоступны, и код с COMConnector или ADODB.Stream просто не выполнится в серверном контексте.
Что остаётся на Linux: встроенный НТТР-клиент (НТТРСоединение, НТТРЗапрос, НТТРОтвет), работа с двоичными данными и файлами, временное хранилище для передачи картинки на клиент управляемой формы. Тонкий клиент на рабочей станции Windows тут ни при чём: если QR строите на сервере (&НаСервере), ограничение определяет ОС сервера, а не место, откуда пользователь зашёл в базу.
Я исхожу из сценария «внешний генератор отдаёт PNG по GET с параметрами текста и размера». Локальная генерация без сети возможна отдельно (обработка, расширение, подсистема штрихкодов в вашей конфигурации), но в этой статье держу одну линию: HTTP наружу, ответ как изображение, вывод через временное хранилище.
Сопоставьте исходный СОМ-подход с тем, что меняем
Я сначала раскладываю старый код по слоям: где HTTP, где файл, где макет. Так проще не тащить COM в новый модуль по привычке.
Модули формы и серверная функция генерации QR
В ранней публикации DanilaDru схема строится на Microsoft.XMLHTTP: open/send, затем responseBody в файл через ADODB.Stream (Type=1, SaveToFile). Классическая схема сводится к трём операциям: сформировать URL с закодированным текстом QR, скачать байты картинки, положить их в файл или сразу в макет печати. COM закрывает первые две задачи на Windows; на Linux их нужно закрыть платформой.
Запись бинарного буфера в файл через ADODB.Stream на Linux не повторяется один в один. Вместо Stream я использую либо НТТРСоединение.Получить с сохранением в путь, либо НТТРОтвет.ПолучитьТелоКакДвоичныеДанные() и ЗаписьДвоичныхДанных во временный каталог сервера. Объект Картинка принимает путь к файлу или двоичные данные, если ваша версия платформы это поддерживает для PNG.
Печатная часть в исходниках обычно не зависит от COM: макет документа, область «Код», рисунок с свойством Картинка. Меняется только источник байтов PNG. Адрес временного хранилища нужен там, где картинку показывают на форме (реквизит типа Картинка привязан к адресу, а не к пути на диске клиента).
// Фрагмент логики, которую заменяем (Windows + COM), для ориентира
// XMLHTTP.open("GET", URL,...); XMLHTTP.send(); responseBody -> файл PNG
// Целевая логика на Linux (сервер):
// HTTPСоединение + HTTPЗапрос -> двоичное тело -> Картинка -> ПоместитьВоВременноеХранилище
Соберите НТТРСоединение и запрос к генератору QR
На схеме обмена видно, что платформа сама закрывает и запрос, и бинарный ответ: внешний генератор отдаёт только PNG.
Запрос 1С и ответ PNG от внешнего генератора
Старый публичный endpoint Google Chart API (chart.apis.google.com, параметры cht=qr, chs, chl) снят с эксплуатации. Алгоритм из статей начала 2010-х на нём больше не опирается: запрос вернёт ошибку или пустоту. Я сохраняю ту же идею URL (текст QR в query, размер в параметрах), но указываю актуальный НТТРС-сервис, который по договорённости с ИБ допустим у вас. В примере кода ниже хост и путь заданы условно как «СерверQР» и «/create-qr-code/», по документации выбранного вами сервиса (аналоги по смыслу: ответ image/png, GET, параметры data/size).
Текст внутри QR я собираю из реквизитов заказа: номер, перевод строки, наименование контрагента. Пробелы в query лучше не заменять на «+» вручную, если дальше идёт штатное УРЛ-кодирование. Я использую КодироватьСтроку(СтрокаДанных, СпособКодированияСтроки.КодировкаУРЛ) вместо локальной функции EncodeURL из чужих публикаций, если только у вас в конфигурации уже нет единого модуля кодирования для интеграций.
Критичная деталь НТТРСоединение: в конструктор передаётся имя сервера без префикса « и без « Если передать полный URL как «сервер», платформа часто отвечает, что сервер недоступен. Для HTTPS задаю порт 443 и защищённое соединение (в 8.3 это ЗащищенноеСоединениеОренССЛ или аналог в вашем релизе; проверьте синтаксис в справке к своей версии).
&НаСервере
Функция ТекстQRПоЗаказу(ЗаказСсылка) Экспорт
Номер = СокрЛП(ЗаказСсылка.Номер);
Контрагент = СокрЛП(ЗаказСсылка.Контрагент.Наименование);
Возврат Номер + Символы.ПС + Контрагент;
КонецФункции
&НаСервере
Функция URLПутьQR(ТекстQR, РазмерПикселей) Экспорт
// Пример для сервиса формата api.qrserver.com: /create-qr-code/?size=230x230&data=...
Закодировано = КодироватьСтроку(ТекстQR, СпособКодированияСтроки.КодировкаURL);
Размер = Формат(РазмерПикселей, "ЧГ=0") + "x" + Формат(РазмерПикселей, "ЧГ=0");
Возврат "/create-qr-code/?size=" + Размер + "&data=" + Закодировано;
КонецФункции
&НаСервере
Функция ПолучитьPNGQRЧерезHTTP(ТекстQR, РазмерПикселей = 230) Экспорт
ИмяСервера = "api.qrserver.com"; // без схемы
Порт = 443;
Таймаут = 30; // секунд, подберите под вашу сеть
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено);
Соединение = Новый HTTPСоединение(ИмяСервера, Порт,,,, Таймаут, ЗащищенноеСоединение);
Путь = URLПутьQR(ТекстQR, РазмерПикселей);
Запрос = Новый HTTPЗапрос(Путь);
Запрос.Заголовки.Вставить("User-Agent", "1C-Enterprise/8.3");
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
ТекстОшибки = "HTTP " + Формат(Ответ.КодСостояния, "ЧГ=0");
// при необходимости прочитать тело как строку для журнала
ВызватьИсключение "Не удалось получить QR: " + ТекстОшибки;
КонецЕсли;
Возврат Ответ.ПолучитьТелоКакДвоичныеДанные();
КонецФункции
Устаревший вариант с единой строкой «хост + query» в конструкторе НТТРСоединение и методом Получить иногда встречается в старых перепостах. Я предпочитаю явный НТТРЗапрос: проще менять заголовки, повторять запрос при редиректе (если политика сервиса меняется) и логировать путь без пароля в URL.
Таймаут в конструкторе НТТРСоединение стоит задать явно. Без него «зависший» DNS или фильтр на исходящем HTTPS даёт пустой реквизит на форме без понятной ошибки для пользователя. Я дополнительно пишу код состояния и фрагмент тела в журнал регистрации при ошибке, чтобы отличить «сеть» от «неверный путь».
Превратите ответ в PNG и адрес временного хранилища
Цикл от ссылки на заказ до реквизита формы я держу в голове целиком: иначе легко потерять шаг с идентификатором временного хранилища.
От заказа до поля картинки и печати
Двоичные данные из НТТРОтвет нужно превратить в объект Картинка и передать на клиент формы. Путь через диск сервера Linux остаётся рабочим: ПолучитьИмяВременногоФайла("png"), запись через ЗаписьДвоичныхДанных, затем Новый Картинка(Путь). На части релизов можно сократить цепочку: Новый Картинка(ДвоичныеДанные) без файла, если PNG корректный и платформа принимает формат из памяти.
ПоместитьВоВременноеХранилище(Картинка, УникальныйИдентификатор) возвращает адрес, который присваивают реквизиту формы или передают на клиент параметром. В качестве второго аргумента я передаю УникальныйИдентификатор формы (или объекта), чтобы связать данные с сеансом и не смешивать картинки между пользователями. После обновления адреса на форме вызывают элемент показа (ПриИзменении реквизита или явное обновление), иначе поле картинки иногда остаётся пустым до следующего открытия.
&НаСервере
Функция АдресQRВоВременномХранилище(ЗаказСсылка, ИдентификаторФормы) Экспорт
ТекстQR = ТекстQRПоЗаказу(ЗаказСсылка);
ДвоичныеPNG = ПолучитьPNGQRЧерезHTTP(ТекстQR, 230);
ИмяФайла = ПолучитьИмяВременногоФайла("png");
Запись = Новый ЗаписьДвоичныхДанных(ИмяФайла);
Запись.Записать(ДвоичныеPNG);
Запись.Закрыть();
КартинкаQR = Новый Картинка(ИмяФайла);
УдалитьФайлы(ИмяФайла); // если политика ИБ разрешает; иначе оставить на очистку ОС
Возврат ПоместитьВоВременноеХранилище(КартинкаQR, ИдентификаторФормы);
КонецФункции
&НаКлиенте
Процедура ОбновитьQR(Команда)
Если Не ЗначениеЗаполнено(Объект.Ссылка) Тогда
Возврат;
КонецЕсли;
АдресКартинки = АдресQRВоВременномХранилище(Объект.Ссылка, УникальныйИдентификатор);
QRКартинка = АдресКартинки;
КонецПроцедуры
Реквизит формы QРКартинка имеет тип Строка (адрес во временном хранилище) или Картинка, в зависимости от того, как у вас настроена привязка; в обоих случаях источник один: адрес из ПоместитьВоВременноеХранилище. Для списка документов не вызывайте HTTP на каждую строку без необходимости: кэш по ссылке или генерация по кнопке снимают лишнюю нагрузку с сервера и внешнего сервиса.
Выведите QR в табличный документ через макет
Сценарий печати повторяет исходные публикации: табличный документ, макет с областью и рисунком. COM тут не участвует, если PNG уже лежит в файле или в объекте Картинка в памяти сервера.
Я получаю двоичные данные тем же НТТР-вызовом, сохраняю во временный файл, подставляю в рисунок области макета и вывожу область в табличный документ. Альтернатива: один раз положить картинку во временное хранилище и на сервере печати взять из хранилища, если у вас уже есть адрес с формы.
&НаСервере
Функция ТабличныйДокументСQR(ЗаказСсылка) Экспорт
ТабДок = Новый ТабличныйДокумент;
ИмяФайла = ПолучитьИмяВременногоФайла("png");
ДвоичныеPNG = ПолучитьPNGQRЧерезHTTP(ТекстQRПоЗаказу(ЗаказСсылка), 230);
Запись = Новый ЗаписьДвоичныхДанных(ИмяФайла);
Запись.Записать(ДвоичныеPNG);
Запись.Закрыть();
// МакетПечатиКода - имя макета в вашей конфигурации документа заказа
Макет = Документы.ЗаказПокупателя.ПолучитьМакет("МакетПечатиКода");
Область = Макет.ПолучитьОбласть("Код");
Область.Рисунки.КодРисунок.Картинка = Новый Картинка(ИмяФайла);
ТабДок.Вывести(Область);
УдалитьФайлы(ИмяФайла);
Возврат ТабДок;
КонецФункции
Имена «ЗаказПокупателя», «МакетПечатиКода», «КодРисунок» в вашей базе могут отличаться; подставьте макет из того документа, для которого делаете QR. Размер области макета и параметр size в запросе лучше согласовать, иначе QR визуально мелкий или обрезанный в ячейке.
Отловите типовые ошибки при проверке результата
Сообщение о недоступности сервера при «правильном» URL чаще всего означает, что в НТТРСоединение передали строку с « или целиком URL с path. Разделите: имя хоста, порт, SSL, путь в НТТРЗапрос.
Код состояния не 200: логируйте код и тело ответа. Для внешних сервисов тело иногда текстовое с описанием (лимит, неверный параметр). Пустая картинка на форме при отсутствии исключения проверьте: не глотаете ли ошибку в пустом try, не очищается ли реквизит после неудачного HTTP, не блокирует ли прокси исходящий HTTPS с сервера 1С.
Кодировка текста QR: кириллица в chl/data должна быть УРЛ-кодирована; иначе сканируется мусор или пустая строка. Если в QR нужен JSON или URL с символом &, не склеивайте query вручную без кодирования каждой части.
Каталог временных файлов на Linux у процесса ragent должны быть права на запись. Ошибка записи двоичных данных проявляется как исключение при Запись.Записать или при создании Картинка из битого файла нулевого размера. Я после неудачи смотрю размер файла на диске и первые байты PNG (ожидается сигнатура PNG).
Контекст выполнения: код с НТТРСоединение на клиенте Linux (тонкий клиент на Kubuntu и т.п.) упирается в другие ограничения политики безопасности и исходящих соединений клиента. Статья ориентирована на серверный вызов &НаСервере, где типичен сервер приложений на Linux после миграции с Windows.
Подберите актуальный endpoint и учтите эксплуатацию
Передача номера заказа и наименования контрагента на чужой URL - утечка персональных или коммерческих данных. Для прода я бы не использовал публичный бесплатный генератор без оценки ИБ: свой НТТР-сервис в периметре, локальная генерация (внешняя обработка без отправки данных наружу) или API по договору с фиксированным составом полей.
Если в конфигурации уже есть штатная генерация штрих- и QР-кодов (БСП, типовые подсистемы печати этикеток), имеет смысл сначала проверить её на Linux. HTTP наружу оставляют, когда нужен быстрый прототип, единый формат с легасу-кодом на chart API или когда свой сервис ещё не развёрнут.
Для своего сервиса контракт обычно проще, чем у chart: POST с JSON и ответ PNG, или GET с одним параметром data. Тогда меняется только функция УРЛПутьQР и разбор ответа; цепочка «двоичные данные, Картинка, временное хранилище, макет» остаётся.
Мониторинг: периодически проверяйте доступность endpoint с сервера 1С (curl с той же машины, что ragent, если политика позволяет) и наличие обновлений OpenSSL в ОС. После обновления платформы перечитайте справку по ЗащищенноеСоединение: в новых релизах иногда добавляют параметры сертификатов для корпоративных МИТМ-прокси.
Краткий FAQ
Можно ли оставить COM, если часть пользователей на Windows?
На сервере Linux COM не вернуть для серверного кода. Разветвление «Windows клиент + COM» и «Linux сервер + НТТРСоединение» быстро расходится; я держу один серверный путь НТТРСоединение для всех клиентов.
Почему не вызывать Google Chart API «как в старой статье»?
Сервис chart.apis.google.com выведен из эксплуатации. Тот же алгоритм параметров cht/chs/chl переносите на другой генератор или свой URL, с HTTPS и проверкой кода ответа.
Что проверить первым делом, если на форме пусто?
Код состояния HTTP, имя сервера без схемы, УРЛ-кодирование текста QR, адрес из ПоместитьВоВременноеХранилище в реквизите формы и права на temp на сервере Linux.
Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.