Как правильно прикрепить файлы к управляемой форме на веб-клиенте 1С?

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

Прикрепление файлов к объектам информационной базы через управляемую форму в веб-клиенте 1С – это частая задача, которая имеет свои особенности, обусловленные ограничениями веб-среды и клиент-серверной архитектурой платформы 1С. Мы разберем основные принципы, распространенные ошибки и предоставим пошаговое руководство для реализации такого функционала.

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

Понимание проблемы: почему "просто скопированный код" не работает?

Когда вы переносите код из одного места в другое, особенно в контексте 1С, где тесно связаны форма, сервер и клиент, часто возникают ошибки, если не учитывать контекст выполнения. Основные проблемы, с которыми столкнулся автор:

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

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

Особенности работы с файлами в веб-клиенте 1С

Прежде чем перейти к решению, давайте рассмотрим ключевые моменты, которые необходимо учитывать при работе с файлами в веб-клиенте:

  1. Асинхронность: Большинство операций с файлами (выбор, помещение, получение) должны выполняться асинхронно, чтобы не блокировать интерфейс пользователя. Для этого используются оператор Ждать и асинхронные процедуры (Асинх).
  2. Временное хранилище: При загрузке файла с клиента на сервер он сначала помещается во временное хранилище на сервере. Это промежуточное звено, из которого файл затем можно переместить в постоянное хранилище базы данных. Адрес файла во временном хранилище – это ключ к его данным.
  3. Постоянное хранение: Для долговременного хранения файлов в информационной базе используются либо реквизиты типа ХранилищеЗначения в объектах данных (например, справочниках, документах), либо стандартная подсистема "Работа с файлами" из Библиотеки стандартных подсистем (БСП), которая предоставляет более гибкие механизмы, включая версионирование и хранение файлов в томах.

Устаревшие и актуальные методы прикрепления файлов

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

Устаревший подход: НачатьПомещениеФайла / НачатьПомещениеФайлов

Изначально автор использовал следующий код:


&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
    ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьВыборФайла", ЭтаФорма);
    ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
    НачатьПомещениеФайлов(ОписаниеОповещения, , ДиалогОткрытияФайла, Истина, УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьВыборФайла(ПомещенныеФайлы,ДополнительныеПараметры) Экспорт
    Если ПомещенныеФайлы = Неопределено Тогда
        Возврат;
    КонецЕсли;
    Для каждого ПереданныйФайл Из ПомещенныеФайлы Цикл
        ПутьКФайлу = ПереданныйФайл.Имя;
        Запись.ИмяФайла = РазборСтроки(ПутьКФайлу, "\"); // <-- Здесь первая проблема
        Элементы.ОткрытьФайл.Заголовок = Запись.ИмяФайла;
        Адрес = ПереданныйФайл.Хранение;
    КонецЦикла;
КонецПроцедуры

Этот подход использует метод НачатьПомещениеФайлов, который является немодальным и вызывает процедуру оповещения после выбора файла. В процедуру оповещения ОбработатьВыборФайла передается коллекция ПомещенныеФайлы, где каждый элемент содержит имя файла и адрес во временном хранилище. Проблема этого кода в том, что переменные Запись, РазборСтроки, Элементы.ОткрытьФайл не существуют в контексте новой формы автора, что приводит к ошибкам. Кроме того, метод НачатьПомещениеФайла не рекомендуется к использованию с платформы 8.3.15, так как появились более унифицированные и удобные методы.

Актуальный подход: ПоместитьФайлНаСерверАсинх / НачатьПомещениеФайловНаСервер

С версии 8.3.15 платформы 1С рекомендуется использовать методы ПоместитьФайлНаСерверАсинх или НачатьПомещениеФайловНаСервер. Они также асинхронны, но предоставляют более гибкие возможности настройки диалога выбора файлов и возвращают результат, который можно обработать с помощью оператора Ждать.

Именно такой подход был предложен нашим читателям в ответ на его проблему. Давайте подробно разберем этот вариант решения.

Пошаговое решение: Прикрепление файла с использованием ПоместитьФайлНаСерверАсинх

Мы будем использовать предложенный в обсуждении код и объясним каждый его шаг, а также как адаптировать его под вашу конкретную задачу.

Шаг 1: Выбор файла на клиенте

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


&НаКлиенте
Асинх Процедура ВыбратьФото(Команда)
    // Дополнительная проверка, если нужно
    Если НЕ ЗначениеЗаполнено(ЭтотОбъект.Комментарий) Тогда
        ПоказатьПредупреждение(,"Заполните комментарий !!!");
        Возврат;
    КонецЕсли;

    // Вызываем асинхронный метод для помещения файла на сервер
    Результат = Ждать ПоместитьФайлНаСерверАсинх;

    // Проверяем результат операции
    Если Результат <> Неопределено И Не Результат.ПомещениеФайлаОтменено Тогда
        Попытка
            // Передаем данные на сервер для сохранения
            ВыбратьФотоНаСервере(ВладелецФормы.Объект.Ссылка, Результат.Адрес, Результат.СсылкаНаФайл.Имя); // <-- Здесь была проблема
            ЭтаФорма.Закрыть(); // Возможно, закрытие формы после выбора
        Исключение
            ТекстСообщения = КраткоеПредставлениеОшибки(ИнформацияОбОшибке);
            ПоказатьПредупреждение(,ТекстСообщения);
        КонецПопытки;
    КонецЕсли;
КонецПроцедуры
  1. &НаКлиенте Асинх Процедура ВыбратьФото(Команда): Объявляем клиентскую процедуру, которая будет вызываться, например, по нажатию кнопки. Ключевое слово Асинх указывает на асинхронный характер процедуры, что позволяет использовать оператор Ждать.
  2. Проверка заполнения: Строки с ЗначениеЗаполнено(ЭтотОбъект.Комментарий) являются примером дополнительной логики, которая может быть вам не нужна или должна быть адаптирована под ваши реквизиты.
  3. Результат = Ждать ПоместитьФайлНаСерверАсинх;: Это центральная часть. Метод ПоместитьФайлНаСерверАсинх открывает диалог выбора файла для пользователя. Оператор Ждать заставляет выполнение кода приостановиться до тех пор, пока пользователь не выберет файл или не отменит операцию. Результатом является объект, содержащий информацию о выбранном файле.
  4. Обработка результата:
    • Результат <> Неопределено: Проверяем, что операция не была прервана системой.
    • Не Результат.ПомещениеФайлаОтменено: Проверяем, что пользователь не отменил выбор файла в диалоге.
  5. Вызов серверной процедуры: Если файл успешно выбран, мы вызываем серверную процедуру ВыбратьФотоНаСервере, передавая ей необходимые параметры. Здесь и возникает основная проблема автора с ВладелецФормы.Объект.Ссылка, которую мы рассмотрим далее.

Шаг 2: Обработка файла на сервере и постоянное хранение

После того как файл помещен во временное хранилище на сервере, нам нужно его оттуда забрать и сохранить в постоянном месте – в информационной базе.


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

        // Добавляем новую строку в табличную часть для хранения информации о файле
        НоваяСтрокаФайла = ОбъектВладелец.СписокФото.Добавить(); // "СписокФото" - пример табличной части
        НоваяСтрокаФайла.ИмяФайла = ИмяФайла;
        // НовСтр.Комментарий = СокрЛП(ЭтотОбъект.Комментарий); // Если комментарий передан как параметр
                                                               // Или берется из реквизитов формы-владельца

        // Получаем двоичные данные файла из временного хранилища
        НоваяСтрокаФайла.Фото = Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(СсылкаНаФайлВХранилище));

        // Записываем изменения в объект
        ОбъектВладелец.Записать();
    Исключение
        ВызватьИсключение "Ошибка сохранения файла на сервере: " + ОписаниеОшибки();
    КонецПопытки;
КонецПроцедуры

Давайте разберем эту серверную процедуру:

  1. &НаСервере Процедура ВыбратьФотоНаСервере(...): Это серверная процедура, которая выполняется на сервере 1С.
  2. Параметры процедуры:
    • Док: Это ссылка на объект (например, документ или элемент справочника), к которому мы хотим прикрепить файл. В исходном примере автора была ошибка с ВладелецФормы.Объект.Ссылка. Критически важно: Если ваша текущая форма не является формой элемента справочника или документа, то ВладелецФормы.Объект.Ссылка не будет существовать. Вам нужно определить, к какому объекту в базе вы хотите привязать файл, и передать его ссылку (или сам объект) в эту процедуру в качестве параметра Док. Например, если форма открыта для нового документа, вы можете передать пустую ссылку, а после записи документа обновить ссылку. Если форма открыта для уже существующего объекта, передайте Объект.Ссылка текущей формы.
    • СсылкаНаФайлВХранилище: Этот параметр соответствует Результат.Адрес из клиентской процедуры. Это адрес, по которому файл временно хранится на сервере.
    • ИмяФайла: Этот параметр соответствует Результат.СсылкаНаФайл.Имя из клиентской процедуры. Это имя, которое выбрал пользователь на клиенте.
  3. ОбъектВладелец = Док.ПолучитьОбъект();: Мы получаем объект (документ, справочник), к которому будет прикреплен файл, чтобы работать с его реквизитами.
  4. НоваяСтрокаФайла = ОбъектВладелец.СписокФото.Добавить();: Здесь предполагается, что у вашего объекта ОбъектВладелец есть табличная часть, например, с именем СписокФото, куда вы будете добавлять информацию о прикрепленных файлах. Если у вас нет такой табличной части, вам нужно ее создать или использовать другой механизм хранения (например, отдельный справочник "ПрисоединенныеФайлы").
  5. НоваяСтрокаФайла.ИмяФайла = ИмяФайла;: Сохраняем имя файла.
  6. НоваяСтрокаФайла.Фото = Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(СсылкаНаФайлВХранилище));: Это самый важный шаг для сохранения данных файла.
    • ПолучитьИзВременногоХранилища(СсылкаНаФайлВХранилище): Эта функция возвращает двоичные данные файла, используя переданный адрес из временного хранилища.
    • Новый ХранилищеЗначения(...): Полученные двоичные данные помещаются в объект ХранилищеЗначения. Это стандартный механизм 1С для хранения произвольных двоичных данных (файлов, изображений) непосредственно в информационной базе.
  7. ОбъектВладелец.Записать();: Сохраняем измененный объект (документ, справочник) в базе данных.

Решение проблемы с ВладелецФормы.Объект.Ссылка

Основная причина ошибки автора заключалась в непонимании, что такое ВладелецФормы.Объект.Ссылка. Давайте рассмотрим подробнее.

Когда вы видите ВладелецФормы.Объект.Ссылка в примере кода, это означает, что форма, в которой этот код выполняется, должна иметь "владельца", и у этого владельца должен быть реквизит Объект (обычно это происходит, когда форма является формой элемента справочника или документа, и свойство Объект содержит данные этого элемента), и у этого Объекта должно быть свойство Ссылка.

В вашей ситуации, если форма является формой документа или справочника, вы можете передать ее собственную ссылку:


// Вместо ВладелецФормы.Объект.Ссылка
ВыбратьФотоНаСервере(Объект.Ссылка, Результат.Адрес, Результат.СсылкаНаФайл.Имя);

Если же ваша форма не является формой объекта (например, это форма обработки или какой-то вспомогательной формы), и вы хотите привязать файл к определенному документу или элементу справочника, то вам нужно сначала получить ссылку на этот объект, а затем передать ее в серверную процедуру. Например:


// Если ссылка на документ хранится в реквизите формы "ДокументДляПрикрепления"
ВыбратьФотоНаСервере(РеквизитФормы.ДокументДляПрикрепления, Результат.Адрес, Результат.СсылкаНаФайл.Имя);

Самое главное – это корректно определить, к какому именно объекту информационной базы вы хотите прикрепить файл, и передать его ссылку в серверную процедуру в качестве первого параметра. В приведенном примере ВыбратьФотоНаСервере этот параметр назван Док.

Организация постоянного хранения присоединенных файлов

Как мы уже выяснили, файлы нельзя хранить в реквизитах формы. Их необходимо сохранять в информационной базе.

1. Хранение в реквизите типа ХранилищеЗначения

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

2. Использование стандартной подсистемы "Работа с файлами" (БСП)

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

Подключение этой подсистемы требует определенных шагов по интеграции в вашу конфигурацию, включая:

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

БСП предоставляет готовые механизмы как для хранения файлов непосредственно в базе данных, так и для хранения во внешних томах (на файловом сервере), что очень важно для больших объемов данных.

Ключевые моменты и рекомендации для успешной реализации

  1. Внимательно к контексту выполнения: Всегда проверяйте, существуют ли переменные, реквизиты и функции, используемые в примерах кода, в вашей форме и в вашем модуле. Адаптируйте имена реквизитов, табличных частей и параметров под свою структуру.
  2. Используйте отладчик: Активное использование отладчика – ваш лучший помощник. Он позволит вам пошагово отследить выполнение кода, увидеть значения всех переменных (например, что содержит Результат после Ждать ПоместитьФайлНаСерверАсинх, или почему ВладелецФормы оказался неопределенным) и точно локализовать причину ошибки.
  3. Асинхронные операции обязательны: Для веб-клиента всегда используйте асинхронные методы для работы с файлами, чтобы избежать блокировки интерфейса пользователя.
  4. Понимание Результат.Адрес и Результат.СсылкаНаФайл.Имя:
    • Результат.Адрес: Это строка, содержащая адрес файла во временном хранилище на сервере. Именно этот адрес нужно передавать в серверную функцию ПолучитьИзВременногоХранилища().
    • Результат.СсылкаНаФайл.Имя: Это полное имя файла, выбранное пользователем на клиенте (например, "Документ.pdf"). Вы можете использовать его для сохранения файла с оригинальным именем.
  5. Постоянное хранение: Всегда планируйте, как и где файлы будут храниться постоянно. Не полагайтесь на реквизиты формы.
  6. Стандартные подсистемы: Если у вас нет специфических требований, и вы работаете с современной версией платформы, рассмотрите возможность использования стандартной подсистемы "Присоединенные файлы" из БСП. Это значительно сократит время на разработку и обеспечит надежный функционал.

Надеемся, это подробное объяснение поможет вам успешно реализовать функционал прикрепления файлов в ваших управляемых формах на веб-клиенте 1С.

← На главную