Как исправить ошибку создания двоичных данных из файла в веб-клиенте 1С?

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

При переходе с тонкого клиента на веб-клиент разработчики часто сталкиваются с тем, что код, отвечающий за выбор и чтение файлов, перестает работать. Ошибка обычно возникает на строке Новый ДвоичныеДанные(ПутьКФайлу). Проанализируем ситуацию: в среде веб-браузера прямая работа с файловой системой пользователя ограничена политиками безопасности. Браузер не позволяет коду 1С просто так «взять» файл по абсолютному пути с диска C:\. Рассмотрим, почему это происходит и как переписать код под современные стандарты платформы 1С.

Выясним причину: почему старый код не работает

В веб-клиенте конструктор Новый ДвоичныеДанные(), принимающий путь к файлу, недоступен. Это связано с тем, что веб-браузер работает в изолированной среде («песочнице»). Программный доступ к локальным файлам возможен только через интерактивное действие пользователя (выбор файла в системном диалоге). Более того, даже если вы получили путь к файлу, веб-клиент не сможет его прочитать синхронно. Ранее для обхода этих ограничений использовалось специальное «Расширение работы с файлами», но современные браузеры (Chrome, Firefox, Safari) отказываются от поддержки подобных плагинов. Поэтому 1С перешла на асинхронную модель работы.

Решение 1: Использование современного метода ПоместитьФайлыНаСерверАсинх

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

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


&НаКлиенте
Асинх Процедура ЗагрузитьИсходныйДокумент(Команда)

    // Описываем параметры выбора файлов
    ПараметрыЗагрузки = Новый ПараметрыПомещенияФайлов;
    ПараметрыЗагрузки.МножественныйВыбор = Ложь;
    ПараметрыЗагрузки.Фильтр = "Файлы Excel (*.xls;*.xlsx)|*.xls;*.xlsx";

    // Вызываем диалог и загрузку асинхронно
    РезультатЗагрузки = Ждать ПоместитьФайлыНаСерверАсинх(,,, ПараметрыЗагрузки, УникальныйИдентификатор);

    // Проверяем, выбрал ли пользователь файл
    Если РезультатЗагрузки = Неопределено Тогда
        Возврат;
    КонецЕсли;

    // Получаем данные о загруженном файле
    ДанныеФайла = РезультатЗагрузки[0];
    АдресХранилища = ДанныеФайла.Адрес;
    ИмяФайла = ДанныеФайла.ФайлМетод.Имя;

    // Передаем управление серверной процедуре
    ЗагрузитьИсходникНаСервере(АдресХранилища, ИмяФайла);

КонецПроцедуры

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

Решение 2: Работа на сервере без лишних временных файлов

Проанализируем серверную часть кода. Часто разработчики пытаются сохранить двоичные данные во временный файл на сервере через КаталогВременныхФайлов(), чтобы потом прочитать его в ТабличныйДокумент. Однако, если ваша база работает на Linux или в кластере серверов, это может вызвать дополнительные сложности с правами доступа.

Посмотрим, как можно оптимизировать серверную процедуру, используя чтение напрямую из потока или корректное создание временного файла:


&НаСервере
Процедура ЗагрузитьИсходникНаСервере(Адрес, ИмяФайла)
    
    ТабД = Новый ТабличныйДокумент;
    
    // Получаем данные из хранилища
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);
    
    // Чтобы прочитать данные в ТабличныйДокумент, 1С требует физический файл или поток.
    // Создадим временное имя файла корректно:
    Расширение = СтрРазделить(ИмяФайла, ".", Ложь);
    тПуть = ПолучитьИмяВременногоФайла(Расширение[Расширение.ВГраница()]);
    
    ДвоичныеДанные.Записать(тПуть);
    
    Попытка
        // Для XLSX файлов 1С нативно поддерживает чтение на сервере (в т.ч. на Linux)
        ТабД.Прочитать(тПуть, СпособЧтенияЗначенийТабличногоДокумента.Текст);
    Исключение
        Инфо = ИнформацияОбОшибке();
        ЗаписьЖурналаРегистрации("ЗагрузкаФайла", УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(Инфо));
        ВызватьИсключение "Ошибка чтения файла: " + Инфо.Описание;
    КонецПопытки;

    // Удаляем временный файл сразу после чтения
    Попытка
        УдалитьФайлы(тПуть);
    Исключение
    КонецПопытки;

    // Дальнейшая обработка через ПостроительЗапроса
    // ...
КонецПроцедуры

Важные нюансы при работе в веб-клиенте

Проанализируем еще несколько важных моментов, которые помогут избежать ошибок в будущем:

  1. Отказ от синхронных вызовов: Все методы, заканчивающиеся на ...Асинх, — это стандарт для современного 1С. Старые методы (без приставки Асинх) в веб-клиенте либо требуют расширения, либо вообще не работают.
  2. Объект Файл: В веб-клиенте нельзя создать объект Новый Файл(Путь), чтобы проверить его существование или размер до загрузки. Всю информацию о файле (размер, имя) вы получите только после того, как метод загрузки вернет результат.
  3. Безопасность временного хранилища: При использовании ПоместитьВоВременноеХранилище (или методов, делающих это автоматически), всегда передавайте УникальныйИдентификатор формы. Это гарантирует, что данные будут очищены сервером автоматически при закрытии формы.
  4. Форматы Excel: Помните, что формат .xlsx (XML) читается платформой 1С нативно гораздо стабильнее, чем старый бинарный .xls. Если сервер работает на ОС Linux, убедитесь, что у вас установлены шрифты (пакет ttf-mscorefonts-installer), иначе ТабличныйДокумент может выдать ошибку при формировании областей.

Таким образом, для исправления вашей ошибки необходимо отказаться от ручного создания ДвоичныеДанные на клиенте и доверить выбор и передачу файла методу ПоместитьФайлыНаСерверАсинх. Это сделает ваш код универсальным: он будет одинаково успешно работать и в тонком клиенте, и в любом современном браузере без установки дополнительных компонентов.

← На главную