При разработке подсистем прикрепления документов и файлов к объектам информационной базы часто возникает задача сохранения бинарных файлов в базу данных и их последующего открытия на стороне клиента. Разберем по шагам, как правильно извлечь файл из объекта ХранилищеЗначения, сохранить его на диск и открыть в ассоциированной программе операционной системы, а также проанализируем ошибки, возникающие при реализации такой функциональности.
Файлы в информационной базе сохраняются в виде объекта ДвоичныеДанные, упакованного в ХранилищеЗначения (часто со сжатием). Для того чтобы операционная система смогла открыть файл, его необходимо сначала восстановить из хранилища и сохранить во временный каталог на локальном диске пользователя.
Рассмотрим последовательность действий:
Получить() у реквизита типа ХранилищеЗначения. В результате получаем исходный объект ДвоичныеДанные.ПолучитьИмяВременногоФайла(), передавая в нее расширение файла.Записать() у объекта ДвоичныеДанные, передавая сформированный путь.ЗапуститьПриложение(), которая запускает файл в ассоциированной с данным расширением программе (например, Microsoft Word, Excel или просмотрщике изображений).Посмотрим на пример обработчика события Выбор для элемента формы (например, таблицы или списка регистра сведений), где хранятся записи о прикрепленных файлах:
Процедура РегистрСведенийСписокВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Проверяем наличие данных в хранилище
Если ТекущиеДанные.Файл = Неопределено Тогда
Предупреждение("Файл не найден в базе данных.");
Возврат;
КонецЕсли;
// 1. Извлекаем двоичные данные из хранилища
ДвоичныеДанные = ТекущиеДанные.Файл.Получить();
Если ДвоичныеДанные = Неопределено Тогда
Предупреждение("Не удалось извлечь данные файла.");
Возврат;
КонецЕсли;
// 2. Формируем путь к временному файлу с нужным расширением
Расширение = ТекущиеДанные.РасширениеФайла;
ИмяВременногоФайла = ПолучитьИмяВременногоФайла(Расширение);
// 3. Записываем файл на локальный диск
Попытка
ДвоичныеДанные.Записать(ИмяВременногоФайла);
Исключение
Предупреждение("Ошибка при сохранении файла на диск: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// 4. Открываем файл через системное приложение
ЗапуститьПриложение(ИмяВременногоФайла);
КонецПроцедуры
Проанализируем типовые ошибки, которые часто допускаются при помещении файла в регистр сведений:
При создании набора записей с отбором без вызова метода Прочитать() вызов НаборЗаписей.Записать() полностью очистит существующие записи по этому отбору и запишет только одну новую. Если требуется добавить файл к существующему списку, набор необходимо предварительно прочитать либо использовать объект РегистрСведенийМенеджерЗаписи.
Использование конструкции ПРАВ(_Файл, 3) приводит к ошибкам при работе с файлами с расширениями длиннее трех символов (например, .docx, .xlsx, .html). Для корректного получения расширения следует использовать объект платформы Файл:
ОбъектФайл = Новый Файл(_Файл);
Расширение = ОбъектФайл.Расширение; // Возвращает расширение вместе с точкой, например, ".docx"
ИмяФайла = ОбъектФайл.Имя;
Поиск последнего номера через запрос к регистру без отбора по ключевому полю (владельцу файла) и без явных блокировок в многопользовательской среде может приводить к дублированию номеров записей и ошибкам уникальности ключа записи.
При проектировании механизмов хранения и открытия файлов важно учитывать следующие нюансы:
Клиент-серверное взаимодействие: В управляемом приложении доступ к данным информационной базы и объектам метаданных выполняется исключительно на сервере. Извлечение двоичных данных из базы должно производиться в контексте &НаСервере, после чего данные передаются на клиент (например, через временное хранилище или возвратом ДвоичныеДанные), а методы ПолучитьИмяВременногоФайла(), Записать() и ЗапуститьПриложение() вызываются в контексте &НаКлиенте.
Размер базы данных: Хранение большого количества объемных файлов непосредственно в таблицах информационной базы быстро увеличивает размер файла БД (1Cv8.1CD для файловых баз или базы данных СУБД). Для высоконагруженных систем рекомендуется использовать механизмы хранения файлов на внешних томах диска.