Работа с файлами в 8.3

Управляемые формы теперь называются "интерфейс ТАКСИ", модальные окна запрещены, а режим использования синхронных вызовов расширений и внешних компонент наглухо положил работоспособность большинства этих расширений и внешних компонент, и половину старых методов в добавок.

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

Суть механизма работы с файлами в кратце:

1) На клиенте выбираем файл

2) Пихаем его в чёрный ящик

3) Сохраняем содержимое чёрного ящика на сервере

Загвоздка состоит в том, что делать это надо особенно, по-новому и с душой.

Поэтому

ВыбранныйФайл.Существует()

и прочие языческие штучки здесь не прокатят.

Вот листинг кода, который позволяет загрузить файл с клиента

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

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

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

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

Идём дальше.

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

Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(Адрес));

С одним разобрались, теперь второе - как достать файл из этого хранилища значений (которое, напомню, находится на сервере) и сохранить на диск клиента?

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

Адрес = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ИмяРеквизита");

Будьте, внимательны! Эта навигационная ссылка уже не имеет с временным хранилищем ничего общего! Проверить тип навигационной ссылки можно методом

ЭтоАдресВременногоХранилища(Адрес)

По традиции, листинг кода, который вызывает диалог сохранения файла

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

Значение переменной "Файл" это ещё одна особенность данного способа. Здесь стоит обратить внимание на "ИмяФайла". Дело в том, что помещая файл во временное хранилище, информация о его имени и расширении теряется. Поэтому не забудьте где-нибудь сохранять корректное имя файла, или хотя бы его расширение, чтобы потом не мучаться с вопросом "А это вордовский документ или мп3?"

Метод "НачатьПолучениеФайлов" аналогичен методу "НачатьПомещениеФайлов". Просто один открывает диалог для выбора файла, другой же, наоборот, открывает диалог для сохранения файла.

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

Тонкий клиент

Начнем с самого простого - передачи файла на сервер для тонкого клиента 1С:Предприятия 8.2. Тонкий клиент - это отдельное приложение, которое позволяет работать с конфигурациями в режиме управляемого приложения, а также использует меньше ресурсов клиентской машины по сравнению с толстым клиентом.

Для демонстрации передачи файла в таком режиме создадим тестовую конфигурацию, в которой будет справочник "Файлы" с реквизитами "Хранилище" (тип "Хранилище значения" для хранения двоичных данных файла) и "ИмяФайла" (строковой реквизит, в котором хранится исходное имя прикрепленного файла).

Самое интересное будет в форме элемента этого справочника. Для прикрепления файла с диска клиентского компьютера добавим команду "Прикрепить файл".

По нажатии на кнопку "Прикрепить файл" вызывается диалог выбора файла на диске, а затем его двоичные данные передаются на сторону сервера и записываются в реквизит "Хранилище". На следующем листинге показан программный код обработчика данной команды:

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

Приведенный способ передачи файла с клиента на сервер рабочий, не раз применял его для решения практических задач. Об оптимальности предложенного способа хранения файлов в базе сейчас речь не идет. Единственная проблема, с которой встречался при передаче файла таким образом - это "вылет" платформы, если размер файла был более ~200 МБ. Было это примерно 2 года назад, возможно, такая ситуация была связана больше с качеством соединения, чем с платформой.

WEB-клиент

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

На предыдущем скриншоте показана реакция платформы, при попытке прикрепить файл в веб-клиенте способом, который мы реализовали для тонкого клиента. Описание ошибки явно говорит нам, что для работы с файлами в этом режиме нам нужно установить для браузера плагин "Расширение для работы с файлами". Но и тут не все так просто!

Но обо всем по порядку! Сначала установим расширение для работы с файлами. Для этого по команде "Прикрепить файл", если пользователь работает в режиме веб-клиента, выполним установку компоненты и подключим ее для использования. Вот такой код добавится в начало обработчика:

Первый вызов метода "ПодключитьРасширениеРаботыСФайлами" позволяет определить было ли оно установлено ранее. Если подключение компоненты не было выполнено, то

выполняется его установка и повторная попытка подключения. Но и после этого прикрепить файл не удастся! Вот какая ошибка встретится у нас на пути: "Новый ДвоичныеДанные(<ПутьКФайлу>);"

Как же тогда быть и передать файл на сервер?

Для передачи файлов на сервер в веб-клиенте используется метод "ПоместитьФайлы". Первым параметром метода передается массив элементов типа "ОписаниеПередаваемогоФайла", содержащее полный путь к файлу и адрес во временном хранилище. Вторым параметром передается массив, в который будут помещены результаты передачи файлов на сервер (их адреса во временном хранилище и др. информация). Третий и четвёртый параметр - это флаг интерактивной работы (будут ли выводиться диалоги пользователю) и уникальный идентификатор. Подробнее о работе и синтаксисе данного метода Вы можете узнать в синтаксис помощнике. На следующем изображении демонстрируется пример использования метода "ПоместитьФайлы":

Что касается изменений в серверном вызове, то они незначительные. Если процедура "ПрикрепитьФайлСервер" вызывается с веб-клиента, то сначала производится получение двоичных данных из временного хранилища значений, и уже после записывается в базу данных:

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

Стоит сказать о некоторых подводных камнях, с которыми Вы можете столкнуться. Первое, что нужно обязательно знать - это ограничение веб-клиента платформы при работе с такими браузерами как Google Chrome, Safari или Mozilla Firefox. Установить на них расширение работы с файлами проблематично. С первыми двумя так и не получилось научить веб-клиент загружать файлы на сервер. С Firefox задача также была решена, но после долгих танцев с бубном.

Еще один интересный момент - это ограничение работы с некоторыми типами данных на стороне веб-клиента. Выше была показана подобная проблема на примере конструктора двоичных данных. Эти особенности нужно учитывать при разработке.

Таким образом, веб-клиент имеет весьма ограниченные возможности по работе с файлами на машине пользователя, передачи их на сервер и обратно. К тому же поддержка только двумя браузерами расширения работы с файлами ставит под сомнение использование этого компонента для решения практических задач, ведь очень многие пользователи используют Chrome или Safari. Имеется другой путь передачи файлов в веб-клиенте, но это уже другая история.