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

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

В процессе разработки в среде 1С:Предприятие 8.3 программисты часто сталкиваются с задачей сохранения печатных форм (табличных документов) во внешние файлы с последующим их преобразованием в двоичные данные. Однако иногда привычный код внезапно выдает исключение: «Ошибка при вызове конструктора (ДвоичныеДанные): Недопустимое значение параметра (параметр номер '1')». Проанализируем, почему это происходит, и разберем наиболее надежные способы решения этой задачи.

Разбор ситуации и поиск причины ошибки

Рассмотрим типичный фрагмент кода, который может привести к ошибке. В данном примере мы пытаемся программно сформировать имя файла на основе представления документа, сохранить табличный документ на диск и прочитать его обратно для дальнейшей обработки (например, для отправки по почте или записи в справочник «Присоединенные файлы»):


ИмяФайла = ИмяТабдок + " " + СокрЛП(СтрЗаменить(МассивСсылок[0].Ссылка, "(не проведен)","")) + ".PDF"; 
КаталогВременныхФайлов = КаталогВременныхФайлов();   
ПолноеИмяФайла = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(КаталогВременныхФайлов, ИмяФайла);

ТабДок.Записать(ПолноеИмяФайла, ТипФайлаТабличногоДокумента.PDF);
мФайл = Новый ДвоичныеДанные(ПолноеИмяФайла);

Проанализируем ситуацию через отладчик. Если переменная ПолноеИмяФайла содержит строку вида "E:\Temp\Заказ поставщику 0001 от 18.07.2022 13:08:34.PDF", мы увидим проблему. В операционных системах семейства Windows символ двоеточия : является зарезервированным. Он используется для обозначения логических дисков или альтернативных потоков данных (ADS). Использование двоеточия в основной части имени файла запрещено.

Выясним, почему метод Записать() табличного документа может не выдавать ошибку сразу. В некоторых версиях платформы метод Записать() при наличии двоеточия в середине пути ведет себя коварно: он либо «обрезает» имя файла до первого недопустимого символа, либо создает файл, который фактически недоступен для стандартных методов чтения. В итоге, когда управление переходит к конструктору Новый ДвоичныеДанные(ПолноеИмяФайла), система пытается найти файл по некорректному пути и возвращает ошибку «Недопустимое значение параметра».

Решение №1: Нормализация имени файла

Первый и самый очевидный способ исправления — это очистка имени файла от символов, которые файловая система считает недопустимыми. К таким символам относятся: \ / : * ? " < > |. Рассмотрим, как правильно подготовить строку имени файла.

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


// Очищаем имя от всех запрещенных символов
ИмяФайла = ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла(ИмяФайла, "");

Если же вы пишете код в самописной конфигурации без БСП, можно реализовать простую замену самостоятельно. Проанализируем следующий пример:


НедопустимыеСимволы = "\/:*?""<>|";
Для Индекс = 1 По СтрДлина(НедопустимыеСимволы) Цикл
    СимволЗамены = Сред(НедопустимыеСимволы, Индекс, 1);
    ИмяФайла = СтрЗаменить(ИмяФайла, СимволЗамены, "");
КонецЦикла;

Важный совет: При формировании имен файлов, содержащих дату, всегда используйте формат без двоеточий и точек. Например, формат ГГГГММДДЧЧММСС (20220718130834) не только безопасен, но и позволяет корректно сортировать файлы в папке по алфавиту в хронологическом порядке.

Решение №2: Использование потоков в памяти (MemoryStream)

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

Рассмотрим подробнее этот алгоритм. Мы создаем объект ПотокВПамяти, записываем в него данные табличного документа и сразу получаем ДвоичныеДанные, не создавая ни одного файла на диске.

Разберем этот процесс по шагам в коде:


// 1. Создаем поток в оперативной памяти
ПотокВПамяти = Новый ПотокВПамяти();

// 2. Записываем табличный документ в этот поток в формате PDF
// Обратите внимание: метод поддерживает запись в поток начиная с версии 8.3.9
ТабДок.Записать(ПотокВПамяти, ТипФайлаТабличногоДокумента.PDF);

// 3. Закрываем поток и получаем результат в виде объекта ДвоичныеДанные
ДвоичныеДанныеФайла = ПотокВПамяти.ЗакрытьИПолучитьДвоичныеДанные();

// Теперь ДвоичныеДанныеФайла можно передать на сервер, записать в ИБ или отправить клиенту

Преимущества данного метода:

  1. Скорость: Работа с RAM значительно быстрее, чем операции чтения/записи на HDD/SSD.
  2. Надежность: Исключаются ошибки, связанные с именами файлов, занятостью файлов другими процессами или отсутствием прав на папку Temp.
  3. Безопасность: На сервере не скапливаются временные файлы, которые нужно удалять.
  4. Чистота кода: Вам не нужно использовать КаталогВременныхФайлов() и заботиться об уникальности имен при одновременной работе нескольких пользователей.

Нюансы работы на сервере и клиенте

Посмотрим на ситуацию со стороны архитектуры «клиент-сервер». Если вы формируете файл в коде на стороне сервера (например, в общем модуле), то функция КаталогВременныхФайлов() вернет путь к временной папке пользователя, под которым запущен агент службы 1С (обычно USR1CV8). Если после этого вы попытаетесь обратиться к этому файлу с клиента, вы получите ошибку, так как у клиентской машины нет доступа к локальным папкам сервера.

Именно поэтому использование объекта ДвоичныеДанные в связке с потоками или временным хранилищем является стандартом разработки. Проанализируем правильную цепочку действий:

  1. На сервере формируется ТабличныйДокумент.
  2. С помощью ПотокВПамяти или временного файла на сервере данные конвертируются в ДвоичныеДанные.
  3. Объект ДвоичныеДанные помещается во ВременноеХранилище.
  4. Адрес хранилища передается на клиент для скачивания или отображения.

Заключение

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

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

← На главную