Как получить файлы, хранящиеся в томах на диске, если стандартный OData их не отдает

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

При интеграции сторонних систем с 1С через протокол OData разработчики часто сталкиваются с неприятной особенностью: файлы, которые хранятся непосредственно в базе данных, передаются без проблем, но как только объем данных вынуждает администраторов перенести файлы в тома на диске, запросы к OData начинают возвращать пустые значения. В этой статье мы подробно разберем, почему это происходит, и как реализовать обходное решение, сохранив производительность системы.

Почему OData «не видит» файлы в томах?

Для начала проанализируем ситуацию с точки зрения архитектуры платформы. Когда мы обращаемся к справочнику ПрисоединенныеФайлы через OData, сервис обращается напрямую к таблицам базы данных (SQL или файловой СУБД). Рассмотрим два сценария хранения:

  1. Хранение в базе данных: Двоичные данные файла упакованы в поле типа ХранилищеЗначения. OData умеет извлекать эти данные при использовании суффикса /$value.
  2. Хранение в томах на диске: В самой базе данных вместо двоичных данных хранится лишь ссылка на том и относительный путь к файлу. Физически файл лежит в сетевой папке или локальном каталоге сервера.

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

Разберем альтернативные варианты

Многие разработчики надеются найти «хитрый способ» настройки OData без изменения конфигурации. Однако, как показывает практика и обсуждения экспертов, таких способов в рамках стандартного интерфейса не существует. Рассмотрим, какие пути решения часто предлагают, и почему они могут не подойти:

Единственное верное решение: Создание собственного HTTP-сервиса

Самым эффективным и профессиональным способом решения задачи является создание собственного HTTP-сервиса. Этот подход позволяет нам использовать всю мощь встроенного языка 1С и механизмов Библиотеки стандартных подсистем (БСП). Разберем по шагам, как это реализовать.

Основное преимущество собственного сервиса в том, что мы можем вызвать стандартную функцию БСП РаботаСФайлами.ДвоичныеДанныеФайла(). Эта функция абсолютно универсальна: ей не важно, где физически лежит файл — в базе или в томе. Она сама определит местоположение, проверит права и вернет нам объект ДвоичныеДанные.

Реализация HTTP-сервиса: Шаг за шагом

Предположим, нам нужно получить файл по его уникальному идентификатору (GUID). Проанализируем пример кода для метода GET нашего будущего сервиса.

Сначала создадим в конфигураторе новый объект HTTP-сервис, зададим ему имя (например, FileStorage) и шаблон URL вида /getfile/{ID}.

В модуле этого сервиса опишем функцию обработки запроса:


Функция ПолучитьФайлGet(Запрос)
    
    // Извлекаем идентификатор файла из параметров URL
    ИдентификаторФайла = Запрос.ПараметрыURL.Получить("ID");
    СсылкаНаФайл = Справочники.Файлы.ПолучитьСсылку(Новый УникальныйИдентификатор(ИдентификаторФайла));
    
    Если СсылкаНаФайл.Пустая() Тогда
        Возврат Новый HTTPСервисОтвет(404);
    КонецЕсли;

    // Используем стандартный механизм БСП для получения данных
    // Функция сама определит, лежит файл в томе или в базе
    Попытка
        ДанныеФайла = РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаНаФайл);
    Исключение
        Возврат Новый HTTPСервисОтвет(500); // Ошибка доступа или отсутствие файла на диске
    КонецПопытки;

    // Формируем ответ. Можно вернуть чистые двоичные данные или Base64
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.УстановитьТелоИзДвоичныхДанных(ДанныеФайла);
    Ответ.Заголовки.Вставить("Content-Type", "application/octet-stream");
    
    Возврат Ответ;
    
КонецФункции

Почему это лучше, чем попытки «дожать» OData?

Проанализируем преимущества использования HTTP-сервиса в данной ситуации:

  1. Прозрачность: Вам не нужно знать путь к тому на диске. Функция РаботаСФайлами.ДвоичныеДанныеФайла берет на себя всю рутину по работе с регистром ПутиКФайламВТомах.
  2. Безопасность: HTTP-сервис работает под учетной записью, имеющей права в 1С, и при этом сервер 1С (от имени которого запущен процесс USR1CV8) имеет физический доступ к сетевым дискам. При прямом запросе через внешние инструменты вы могли бы столкнуться с проблемой прав доступа ОС.
  3. Производительность: Вы можете передавать файл потоком, не перегружая память сервера лишними преобразованиями в Base64, если внешняя система умеет принимать бинарный поток.
  4. Гибкость: Если в будущем вы решите использовать облачное хранение (например, S3), ваш HTTP-сервис просто обновится внутри 1С, а внешняя система даже не заметит подмены механизма получения файла.

Нюансы загрузки файлов (POST-запросы)

Если перед вами стоит обратная задача — загрузить файл через OData так, чтобы он попал в том, — ситуация аналогичная. При использовании стандартного метода POST к сущности OData, платформа запишет данные в таблицу БД. Чтобы файл «улетел» в том, в конфигурации должны быть настроены правила перемещения (регламентное задание) или вызываться специфический программный код при записи. Использование собственного HTTP-сервиса для загрузки также является более надежным вариантом, так как позволяет сразу вызвать процедуру РаботаСФайлами.ЗаписатьФайл(), которая мгновенно отправит файл в нужный том согласно настройкам системы.

Резюме: Если ваша конфигурация (например, 1С:Документооборот) настроена на хранение файлов в томах, забудьте о стандартном OData для работы с бинарным контентом. Создание небольшого HTTP-сервиса в расширении — это стандарт де-факто, который сэкономит вам десятки часов отладки и обеспечит стабильную работу интеграции.

← На главную