Как открыть документ Word, сохраненный в базе в виде хранилища значений?

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

Разберем частую задачу в разработке на платформе 1С:Предприятие 8.3 — открытие файла (например, документа Microsoft Word), который физически сохранен внутри базы данных в реквизите с типом ХранилищеЗначения. Часто разработчики пытаются получить навигационную ссылку на этот реквизит и напрямую передать её в методы запуска приложений, что неизбежно приводит к ошибкам. Давайте проанализируем эту ситуацию и рассмотрим правильные современные способы решения.

Анализ ошибки: почему не работает открытие по навигационной ссылке напрямую?

Посмотрим на пример кода, который часто пытаются использовать новички:


ТекДок = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "Доки.ДокХранилище", ТекСтр);
НашФайл = Новый Файл(ТекДок);
Попытка
    ЗапускПриложения(НашФайл);
Исключение
    Сообщить(ОписаниеОшибки()); 
КонецПопытки;

Выясним причину, по которой этот код выдает ошибку. Функция ПолучитьНавигационнуюСсылку() возвращает строку специального внутреннего формата 1С (например, e1cib/data/Документ...). Однако конструктор объекта Файл ожидает физический путь к файлу на диске (например, C:\Temp\document.docx). Операционная система и метод ЗапускПриложения() ничего не знают о внутренних ссылках 1С, поэтому система не может ни найти такой файл, ни запустить его.

Решение 1: Классический алгоритм (через сервер)

Рассмотрим алгоритм, который был предложен на форуме. Суть заключается в том, чтобы "достать" бинарные данные из базы на сервере, передать их на клиент, сохранить во временную папку операционной системы и только потом открыть.

  1. Извлекаем данные из реквизита ХранилищеЗначения в объект ДвоичныеДанные на стороне сервера. Важный нюанс: если данные возвращают Неопределено, убедитесь, что объект был записан в базу перед чтением.
  2. Передаем эти двоичные данные на клиент.
  3. Получаем путь к временной директории пользователя с помощью функции ПолучитьИмяВременногоФайла(), обязательно указав правильное расширение файла (например, "docx").
  4. Записываем файл на диск по указанному пути.
  5. Передаем полный путь к временному файлу в метод запуска приложения.

Пример реализации:


&НаСервере
Функция ПолучитьФайлИзХранилищаНаСервере(ИндексСтроки)
    ТекОбъект = РеквизитФормыВЗначение("Объект");
    ТекСтрока = ТекОбъект.Доки.Получить(ИндексСтроки);
    Возврат ТекСтрока.ДокХранилище.Получить(); // Возвращает тип ДвоичныеДанные
КонецФункции

&НаКлиенте
Процедура ОткрытьДокумент(Команда)
    ДанныеФайла = ПолучитьФайлИзХранилищаНаСервере(Элементы.Доки.ТекущиеДанные.НомерСтроки - 1);
    
    Если ДанныеФайла <> Неопределено Тогда
        // Генерируем уникальное имя во временной папке Windows
        ПутьКФайлу = ПолучитьИмяВременногоФайла("docx"); 
        
        // Сохраняем физически на диск клиента
        ДанныеФайла.Записать(ПутьКФайлу);
        
        // Открываем. Windows сама подберет Word по расширению .docx
        ЗапуститьПриложение(ПутьКФайлу); 
    КонецЕсли;
КонецПроцедуры

Решение 2: Современный подход через асинхронные методы и навигационную ссылку

В современных версиях платформы 1С (начиная с 8.3) и особенно для корректной работы в веб-клиенте настоятельно рекомендуется использовать асинхронные методы. Идея с навигационной ссылкой изначально была хорошей, просто нужно использовать правильные функции платформы.

Разберем по шагам, как заставить платформу саму скачать файл по ссылке во временную папку:

  1. Формируем навигационную ссылку на реквизит табличной части.
  2. Используем метод НачатьПолучениеФайлаССервера() (или аналогичные асинхронные методы работы с файлами), передав туда нашу ссылку.
  3. В обработчике оповещения, когда файл успешно окажется на клиенте, используем НачатьЗапускПриложения().

Такой подход избавляет нас от необходимости вручную гонять ДвоичныеДанные с сервера на клиент, что сильно экономит оперативную память при работе с большими документами.

Решение 3: Использование Библиотеки стандартных подсистем (БСП)

Проанализируем ситуацию глобально: хранение файлов напрямую в табличной части документа в реквизите ХранилищеЗначения сегодня считается устаревшей практикой. Это приводит к разрастанию таблиц базы данных и усложняет поддержку.

Если в вашей конфигурации внедрена "Библиотека стандартных подсистем" (БСП), используйте стандартный механизм Присоединенные файлы. В этом случае вам вообще не придется писать низкоуровневый код с временными путями.

Достаточно будет вызвать готовую процедуру:

РаботаСФайламиКлиент.ОткрытьФайл(СсылкаНаПрисоединенныйФайл);

Что сделает БСП под капотом:

  1. Определит, где хранится файл (в базе данных или в сетевом томе).
  2. Скачает его в рабочий каталог пользователя на компьютере.
  3. Автоматически подберет программу по расширению и запустит её.
  4. Сможет отследить момент, когда пользователь закроет Word, и предложит сохранить изменения обратно в базу 1С (захват и освобождение файлов).

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

← На главную