Как сохранить файл из двоичных данных или макета в 1С (включая Веб-клиент)

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

В процессе разработки в системе 1С:Предприятие часто возникает задача программного извлечения файлов, которые хранятся внутри базы данных — для этого есть обработка выгрузки файлов из базы 1С. Это могут быть макеты с двоичными данными (например, шаблоны Word или Excel), прикрепленные файлы в справочниках или изображения, полученные с мобильного устройства. Основная сложность заключается в том, что код, успешно работающий в толстом или тонком клиенте, часто выдает ошибку доступа в веб-клиенте из-за политик безопасности браузера.

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

Почему возникает «Ошибка доступа к файлу»?

Чаще всего разработчики сталкиваются с ошибкой при использовании метода ДвоичныеДанные.Записать(). Давайте выясним причину. В веб-клиенте 1С работает внутри «песочницы» браузера. Это означает, что веб-приложение не имеет прямого доступа к файловой системе вашего компьютера по соображениям безопасности. Попытка записать файл по прямому пути, например, D:\123.docx, всегда будет приводить к отказу в доступе.

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

Алгоритм извлечения данных из макета или реквизита

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


&НаСервере
Функция ПолучитьДвоичныеДанныеНаСервере(НомерСтроки)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ПрикрепленныеДанные.Данные,
        |   ПрикрепленныеДанные.Расширение
        |ИЗ
        |   Документ.Заявка.ПрикрепленныеДанные КАК ПрикрепленныеДанные
        |ГДЕ
        |   ПрикрепленныеДанные.Ссылка = &Ссылка И ПрикрепленныеДанные.НомерСтроки = &НомерСтроки";
    
    Запрос.УстановитьПараметр("НомерСтроки", НомерСтроки);
    Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
    
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    Если Выборка.Следующий() Тогда
        // Извлекаем двоичные данные из ХранилищаЗначения
        Возврат Выборка.Данные.Получить();
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Важный момент: если данные хранятся в ХранилищеЗначения, обязательно используйте метод Получить(), чтобы извлечь объект ДвоичныеДанные (поможет инструмент вывода факсимиле в печатные формы).

Универсальное решение для Веб-клиента

Чтобы сохранить файл в веб-клиенте, мы должны использовать механизм временного хранилища. Рассмотрим по шагам, как это реализовать:

  1. Проверяем наличие расширения для работы с файлами в браузере.
  2. Получаем двоичные данные на сервере.
  3. Помещаем их во временное хранилище (ВХ) и получаем уникальный адрес.
  4. На клиенте вызываем метод ПолучитьФайл(), передавая этот адрес.

Посмотрим на пример клиентского кода:


&НаКлиенте
Процедура ОткрытьИСохранитьФайл(Команда)
    ТекущаяСтрока = Элементы.ПрикрепленныеДанные.ТекущиеДанные;
    
    #Если ВебКлиент Тогда
        // Подключаем расширение для работы с файлами
        Если Не ПодключитьРасширениеРаботыСФайлами() Тогда
            УстановитьРасширениеРаботыСФайлами();
            ПодключитьРасширениеРаботыСФайлами();
        КонецЕсли;
    #КонецЕсли

    // Получаем данные с сервера
    ДвоичныеДанные = ПолучитьДвоичныеДанныеНаСервере(ТекущаяСтрока.НомерСтроки);
    
    Если ДвоичныеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;

    // Помещаем во временное хранилище
    АдресВХ = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ЭтаФорма.УникальныйИдентификатор);
    
    // Формируем имя файла
    ИмяФайла = "Документ_" + Строка(Новый УникальныйИдентификатор) + "." + ТекущаяСтрока.Расширение;
    
    // Инициируем получение файла пользователем
    // Третий параметр "Истина" открывает диалог выбора пути
    ПолучитьФайл(АдресВХ, ИмяФайла, Истина);
КонецПроцедуры

Использование Новый УникальныйИдентификатор гарантирует, что имена файлов не будут конфликтовать, если пользователь решит сохранить несколько документов подряд.

Современный подход: Асинхронные вызовы

Начиная с версии 1С 8.3.15, использование синхронных методов вроде ПолучитьФайл() считается устаревшим (deprecated) и в некоторых режимах работы браузеров может блокироваться. Рекомендуется переходить на асинхронную модель работы. Вместо ПолучитьФайл() используем НачатьПолучениеФайлаССервера().

Рассмотрим, как изменится наш подход:


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

&НаКлиенте
Процедура ЗавершитьПолучениеФайла(Результат, ДополнительныеПараметры) Экспорт
    Если Результат <> Неопределено Тогда
        Сообщить("Файл успешно передан браузеру для сохранения.");
    КонецЕсли;
КонецПроцедуры

Этот метод более «дружелюбен» к современным браузерам (Chrome, Safari, Firefox), так как он не блокирует интерфейс пользователя во время передачи данных.

Особенности для мобильных приложений

Если ваша задача связана с мобильным приложением (как упоминалось в сообщениях форума), работа с файлами имеет свои нюансы. Мобильная платформа 1С позволяет использовать СредстваМультимедиа для создания фото. Данные снимка можно сразу преобразовать в ДвоичныеДанные и сохранить в базу.

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

Настройка безопасности браузера

Даже при правильном коде веб-клиент может выдавать предупреждения безопасности. Чтобы минимизировать их:

Решение проблемы «Метод объекта не обнаружен» в расширениях

В ходе обсуждения также поднимался вопрос ошибки в общем модуле при использовании факсимиле (удобно через расширение для подстановки факсимиле в формы). Если вы столкнулись с ошибкой Метод объекта не обнаружен (ДвоичныеДанныеФаксимилеФизическогоЛица) в расширении, скорее всего, произошло обновление типовой конфигурации (например, БП 3.0), где разработчики 1С изменили состав общего модуля УправлениеПечатьюБП. В таких случаях рекомендуется выполнить глобальный поиск по конфигурации, чтобы найти новое имя функции или перенести логику формирования факсимиле в свое расширение, используя прямые запросы к регистру сведений ЛичныеКарточки или аналогичным объектам хранения подписей.

Резюмируем: Для сохранения файла из двоичных данных в веб-клиенте 1С основной связкой методов является ПоместитьВоВременноеХранилище() на сервере и ПолучитьФайл() (или его асинхронный аналог) на клиенте. Прямая запись на диск через Записать() в браузере невозможна.

← На главную