В практике интеграции 1С с внешним оборудованием или сторонними веб-сервисами часто возникает задача превратить систему 1С в полноценный веб-сервер. Рассмотрим специфический сценарий: на сервере хранится множество файлов (например, с расширением .dat), которые необходимо отдавать клиентам по HTTP-запросу. При этом логика выдачи должна учитывать идентификатор устройства (id), стартовый номер файла (kusok) и обеспечивать автоматическое инкрементирование номера файла при повторных запросах, а также сброс последовательности по таймауту.
В этой статье мы разберем, как реализовать подобную задачу средствами платформы "1С:Предприятие 8.3", проанализируем архитектуру решения и рассмотрим способы оптимизации производительности.
Нам необходимо обрабатывать URL вида: ip-адрес/bin/get_file.php?kusok=1000&id=1234567890123. Несмотря на расширение .php в адресе, мы можем настроить веб-сервер (Apache или IIS) таким образом, чтобы эти запросы перенаправлялись в 1С. Основная логика должна работать следующим образом:
kusok.id тот же, система должна увеличивать номер файла на 1 относительно предыдущего выданного, игнорируя параметр kusok в URL (до тех пор, пока он не изменится принудительно).id ведутся независимые счетчики.kusok.Для хранения состояния сессий нам понадобятся два регистра сведений. Разберем их назначение:
1. Регистр сведений "СессииУстройств" (периодический, в пределах секунды):
Здесь мы будем фиксировать сам факт обращения.
- Измерение: ИдентификаторУстройства (Строка).
- Ресурс: ДатаПоследнегоЗапроса (Дата/Время).
Этот регистр позволит нам определять, не "протухла" ли сессия (прошло ли более 1.5 минут).
2. Регистр сведений "СостояниеВыдачи":
Здесь хранится информация о том, какой файл был выдан последним.
- Измерение: ИдентификаторУстройства (Строка).
- Ресурс: ПоследнийНомерФайла (Число).
- Ресурс: ТекущийКусок (Число) — для отслеживания изменения базового параметра в URL.
В дереве метаданных 1С создадим новый объект HTTP-сервис. Назовем его, например, FileProvider. В поле "Корневой URL" укажем bin.
Добавим шаблон URL: get_file.php. Внутри шаблона создадим метод GET и назначим ему обработчик в модуле сервиса. Проанализируем пример кода для этого обработчика:
Функция get_file_GET(Запрос)
Параметры = Запрос.ПараметрыЗапроса;
ID_Устройства = Параметры.Получить("id");
НачальныйКусок = Число(Параметры.Получить("kusok"));
ТекущаяДата = ТекущаяДата();
ВремяТаймаута = 90; // 1.5 минуты
// 1. Проверяем таймаут сессии
ЗапросСессии = Новый Запрос;
ЗапросСессии.Текст =
"ВЫБРАТЬ
| Сессии.Период КАК ПоследняяДата
|ИЗ
| РегистрСведений.СессииУстройств.СрезПоследних(, ИдентификаторУстройства = &ID) КАК Сессии";
ЗапросСессии.УстановитьПараметр("ID", ID_Устройства);
Выборка = ЗапросСессии.Выполнить().Выбрать();
НужноНачатьЗаново = Истина;
Если Выборка.Следующий() Тогда
Если (ТекущаяДата - ВыборкаПоследняяДата) < ВремяТаймаута Тогда
НужноНачатьЗаново = Ложь;
КонецЕсли;
КонецЕсли;
// 2. Определяем номер файла
НомерДляВыдачи = 0;
Если НужноНачатьЗаново Тогда
НомерДляВыдачи = НачальныйКусок;
Иначе
// Читаем из регистра СостояниеВыдачи
// Если НачальныйКусок изменился в URL, тоже начинаем заново
// Код получения из СостояниеВыдачи...
// НомерДляВыдачи = ПоследнийНомер + 1;
КонецЕсли;
// 3. Формируем ответ
ПутьКФайлу = ПолучитьПутьКФайлу(НомерДляВыдачи);
Ответ = Новый HTTPСервисОтвет(200);
ФайлНаДиске = Новый Файл(ПутьКФайлу);
Если ФайлНаДиске.Существует() Тогда
Ответ.УстановитьТелоИзФайла(ПутьКФайлу);
Ответ.Заголовки.Вставить("Content-Type", "application/octet-stream");
// Обновляем данные в регистрах
ЗаписатьСостояние(ID_Устройства, НомерДляВыдачи, НачальныйКусок);
Иначе
Ответ.КодСостояния = 404;
КонецЕсли;
Возврат Ответ;
КонецФункции
Рассмотрим важный аспект: передачу бинарных данных. В ранних версиях платформы 1С разработчикам приходилось считывать файл в память и кодировать его в Base64, что приводило к огромным затратам ресурсов. В современных версиях 8.3 крайне рекомендуется использовать метод УстановитьТелоИзФайла(). Это позволяет платформе передавать поток данных напрямую с диска в HTTP-ответ, минуя создание тяжелых объектов в памяти сервера 1С.
Также важно правильно настроить MIME-тип. Если файлы имеют расширение .dat и предназначены для оборудования, заголовок Content-Type: application/octet-stream будет наиболее универсальным решением.
Если по каким-то причинам (например, использование устаревшей версии платформы 8.1 или 8.2 без лицензий на веб-сервисы) вы не можете использовать HTTP-сервисы 1С, существует "гибридный" путь. Вы можете использовать скрипт на языке ASP или PHP, который будет принимать веб-запрос, а затем через COM-соединение (V83.COMConnector) обращаться к 1С для получения логики (какой файл выдать). Рассмотрим пример такого скрипта на ASP:
<%
Dim V8, Conn, kusok, id, fileName
kusok = Request.QueryString("kusok")
id = Request.QueryString("id")
' Подключаемся к 1С
Set V8 = CreateObject("V83.COMConnector")
Set Conn = V8.Connect("Srvr=""ServerName"";Ref=""BaseName"";Usr=""WebUser"";Pwd=""Password"";")
' Вызываем функцию из общего модуля 1С, которая вернет имя файла
fileName = Conn.ОбщийМодульВебСервер.ОпределитьФайл(kusok, id)
' Отдаем файл клиенту
Response.Buffer = False
Dim objStream
Set objStream = Server.CreateObject("ADODB.Stream")
objStream.Type = 1 ' adTypeBinary
objStream.Open
objStream.LoadFromFile("C:\FilesCatalog\" & fileName)
Response.ContentType = "application/x-unknown"
Response.BinaryWrite objStream.Read
objStream.Close
%>
Важно: Этот метод значительно медленнее нативных HTTP-сервисов из-за накладных расходов на создание COM-объекта при каждом запросе. Его стоит использовать только как временное или вынужденное решение.
Выясним, как сделать так, чтобы 1С работала быстро и не "тормозила" при каждом обращении. Основная проблема веб-сервисов 1С — время инициализации сеанса. Если при каждом запросе 1С будет заново запускать сеанс пользователя, время ответа составит несколько секунд.
Для решения этой проблемы необходимо настроить пул соединений в файле публикации default.vrd. Разберем ключевые параметры:
poolSize — количество одновременно удерживаемых открытых сеансов. Если ожидается много параллельных запросов от разных id, увеличьте это значение.sessionMaxAge — время жизни сеанса в пуле.Проанализируем ситуацию, когда что-то пошло не так. Хороший тон веб-разработки — возвращать понятные HTTP-статусы вместо пустых страниц:
id или доступ заблокирован.Попытка...Исключение).Используя объект HTTPСервисОтвет, мы можем гибко управлять этими кодами, что позволит вызывающей стороне (оборудованию) корректно обрабатывать сбои связи или отсутствие данных.
В завершение отметим, что использование 1С в качестве веб-сервера — это мощный инструмент интеграции. Несмотря на то, что специализированные веб-языки (PHP, Go, Python) могут работать быстрее, 1С выигрывает за счет того, что вся бизнес-логика и данные о сессиях находятся в одной базе, что упрощает администрирование и разработку сложных алгоритмов выдачи.