При переходе с тонкого клиента на веб-клиент разработчики часто сталкиваются с тем, что код, отвечающий за выбор и чтение файлов, перестает работать. Ошибка обычно возникает на строке Новый ДвоичныеДанные(ПутьКФайлу). Проанализируем ситуацию: в среде веб-браузера прямая работа с файловой системой пользователя ограничена политиками безопасности. Браузер не позволяет коду 1С просто так «взять» файл по абсолютному пути с диска C:\. Рассмотрим, почему это происходит и как переписать код под современные стандарты платформы 1С.
В веб-клиенте конструктор Новый ДвоичныеДанные(), принимающий путь к файлу, недоступен. Это связано с тем, что веб-браузер работает в изолированной среде («песочнице»). Программный доступ к локальным файлам возможен только через интерактивное действие пользователя (выбор файла в системном диалоге). Более того, даже если вы получили путь к файлу, веб-клиент не сможет его прочитать синхронно. Ранее для обхода этих ограничений использовалось специальное «Расширение работы с файлами», но современные браузеры (Chrome, Firefox, Safari) отказываются от поддержки подобных плагинов. Поэтому 1С перешла на асинхронную модель работы.
Начиная с версии платформы 8.3.18, это самый правильный и удобный способ. Он позволяет выбрать файл и сразу отправить его во временное хранилище на сервере, не требуя установки расширения браузера. Разберем по шагам, как трансформировать ваш код.
Вместо использования ДиалогВыбораФайла и последующего создания двоичных данных, мы используем один асинхронный вызов. Рассмотрим пример реализации на клиенте:
&НаКлиенте
Асинх Процедура ЗагрузитьИсходныйДокумент(Команда)
// Описываем параметры выбора файлов
ПараметрыЗагрузки = Новый ПараметрыПомещенияФайлов;
ПараметрыЗагрузки.МножественныйВыбор = Ложь;
ПараметрыЗагрузки.Фильтр = "Файлы Excel (*.xls;*.xlsx)|*.xls;*.xlsx";
// Вызываем диалог и загрузку асинхронно
РезультатЗагрузки = Ждать ПоместитьФайлыНаСерверАсинх(,,, ПараметрыЗагрузки, УникальныйИдентификатор);
// Проверяем, выбрал ли пользователь файл
Если РезультатЗагрузки = Неопределено Тогда
Возврат;
КонецЕсли;
// Получаем данные о загруженном файле
ДанныеФайла = РезультатЗагрузки[0];
АдресХранилища = ДанныеФайла.Адрес;
ИмяФайла = ДанныеФайла.ФайлМетод.Имя;
// Передаем управление серверной процедуре
ЗагрузитьИсходникНаСервере(АдресХранилища, ИмяФайла);
КонецПроцедуры
В этом примере ключевым является использование ключевого слова Асинх и оператора Ждать. Это позволяет коду выглядеть линейно, оставаясь при этом неблокирующим для браузера. Метод ПоместитьФайлыНаСерверАсинх сам открывает диалог, считывает файл и помещает его во временное хранилище.
Проанализируем серверную часть кода. Часто разработчики пытаются сохранить двоичные данные во временный файл на сервере через КаталогВременныхФайлов(), чтобы потом прочитать его в ТабличныйДокумент. Однако, если ваша база работает на Linux или в кластере серверов, это может вызвать дополнительные сложности с правами доступа.
Посмотрим, как можно оптимизировать серверную процедуру, используя чтение напрямую из потока или корректное создание временного файла:
&НаСервере
Процедура ЗагрузитьИсходникНаСервере(Адрес, ИмяФайла)
ТабД = Новый ТабличныйДокумент;
// Получаем данные из хранилища
ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);
// Чтобы прочитать данные в ТабличныйДокумент, 1С требует физический файл или поток.
// Создадим временное имя файла корректно:
Расширение = СтрРазделить(ИмяФайла, ".", Ложь);
тПуть = ПолучитьИмяВременногоФайла(Расширение[Расширение.ВГраница()]);
ДвоичныеДанные.Записать(тПуть);
Попытка
// Для XLSX файлов 1С нативно поддерживает чтение на сервере (в т.ч. на Linux)
ТабД.Прочитать(тПуть, СпособЧтенияЗначенийТабличногоДокумента.Текст);
Исключение
Инфо = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("ЗагрузкаФайла", УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(Инфо));
ВызватьИсключение "Ошибка чтения файла: " + Инфо.Описание;
КонецПопытки;
// Удаляем временный файл сразу после чтения
Попытка
УдалитьФайлы(тПуть);
Исключение
КонецПопытки;
// Дальнейшая обработка через ПостроительЗапроса
// ...
КонецПроцедуры
Проанализируем еще несколько важных моментов, которые помогут избежать ошибок в будущем:
...Асинх, — это стандарт для современного 1С. Старые методы (без приставки Асинх) в веб-клиенте либо требуют расширения, либо вообще не работают.Новый Файл(Путь), чтобы проверить его существование или размер до загрузки. Всю информацию о файле (размер, имя) вы получите только после того, как метод загрузки вернет результат.ПоместитьВоВременноеХранилище (или методов, делающих это автоматически), всегда передавайте УникальныйИдентификатор формы. Это гарантирует, что данные будут очищены сервером автоматически при закрытии формы..xlsx (XML) читается платформой 1С нативно гораздо стабильнее, чем старый бинарный .xls. Если сервер работает на ОС Linux, убедитесь, что у вас установлены шрифты (пакет ttf-mscorefonts-installer), иначе ТабличныйДокумент может выдать ошибку при формировании областей.Таким образом, для исправления вашей ошибки необходимо отказаться от ручного создания ДвоичныеДанные на клиенте и доверить выбор и передачу файла методу ПоместитьФайлыНаСерверАсинх. Это сделает ваш код универсальным: он будет одинаково успешно работать и в тонком клиенте, и в любом современном браузере без установки дополнительных компонентов.