В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда при попытке сохранить сформированный PDF-файл или любой другой документ из временного хранилища на диск пользователя возникает системная ошибка: «Ошибка при выполнении файловой операции... Значение данного типа невозможно преобразовать для передачи как файл (Неопределено)». Эта проблема носит коварный характер, так как проявляется не постоянно, а «периодически», что затрудняет поиск причин. В этой статье мы подробно разберем механику работы временного хранилища, выясним причины «исчезновения» файлов и научимся писать отказоустойчивый код для сохранения данных.
Для начала проанализируем текст ошибки. Сообщение (Неопределено) в контексте передачи файла означает, что по указанному адресу во временном хранилище (строка вида e1cib/tempstorage/...) больше нет никаких данных. Платформа пытается обратиться к двоичным данным, чтобы передать их на клиентскую сторону, но находит пустоту. Рассмотрим, почему это происходит.
Основная причина кроется в жизненном цикле временного хранилища. В 1С данные во временном хранилище могут существовать разное время в зависимости от того, как они были туда помещены. Если при вызове функции ПоместитьВоВременноеХранилище(Данные, Адрес) не указан второй параметр (УникальныйИдентификатор), то срок жизни данных ограничен одним серверным вызовом. Как только управление возвращается с сервера на клиент, данные автоматически удаляются платформой для экономии оперативной памяти.
Ситуация с сохранением файла осложняется тем, что между помещением файла в хранилище и его получением на диске обычно стоит интерактивное действие — открытие диалогового окна выбора пути сохранения. Рассмотрим типичный ошибочный сценарий:
НачатьПолучениеФайлаССервера.Неопределено.Чтобы данные «дожили» до момента физического сохранения файла на диск, мы должны явно указать платформе, как долго их нужно хранить. Самый надежный способ — привязать адрес во временном хранилище к УникальномуИдентификатору формы. В этом случае данные будут существовать до тех пор, пока открыта текущая форма или пока не будет выполнен новый серверный вызов, явно перезаписывающий этот адрес.
Рассмотрим правильный пример реализации кода на стороне сервера:
&НаСервере
Функция ПодготовитьФайлКСкачиванию(ДанныеФайла)
// Помещаем данные во временное хранилище, привязывая их к текущей форме
Адрес = ПоместитьВоВременноеХранилище(ДанныеФайла, ЭтаФорма.УникальныйИдентификатор);
Возврат Адрес;
КонецФункции
Использование ЭтаФорма.УникальныйИдентификатор гарантирует, что файл не будет удален сразу после выхода из процедуры. Это критически важно при использовании асинхронных методов работы с файлами.
Проанализируем ситуацию с использованием метода НачатьПолучениеФайлаССервера. Этот метод является асинхронным, то есть он не останавливает выполнение кода, а лишь инициирует процесс. Если сразу после вызова этого метода в коде идет закрытие формы или очистка переменных, адрес в хранилище может стать невалидным.
Посмотрим на пример корректного вызова на клиенте, предложенный в обсуждении:
&НаКлиенте
Процедура СохранитьPDF(Команда)
// Получаем адрес файла (на сервере он уже привязан к ИД формы)
ДанныеФайла = ПолучитьДанныеФайлаСервер();
ПараметрыДиалога = Новый ПараметрыДиалогаПолученияФайлов;
ПараметрыДиалога.Заголовок = "Выберите путь для сохранения PDF";
ПараметрыДиалога.Фильтр = "Документ PDF (*.pdf)|*.pdf";
// Важно: Адрес должен быть валидным на всем протяжении диалога
НачатьПолучениеФайлаССервера(ДанныеФайла.АдресВоВременномХранилище, "Отчет.pdf", ПараметрыДиалога);
КонецПроцедуры
В данном примере ДанныеФайла.АдресВоВременномХранилище — это строка-ссылка. Если на сервере при помещении данных был использован УникальныйИдентификатор, то ошибка (Неопределено) не возникнет.
Часто PDF-файлы (особенно тяжелые отчеты) формируются в фоновом задании. Здесь разработчиков подстерегает еще одна ловушка. Временное хранилище фонового задания изолировано и уничтожается вместе с завершением этого задания. Даже если вы получили адрес из фонового задания, на клиенте он будет недоступен.
Проанализируем алгоритм действий при работе с фоновыми заданиями:
ПолучитьИзВременногоХранилища и повторное ПоместитьВоВременноеХранилище, но уже с ИД формы пользователя.Без этого промежуточного шага попытка сохранить файл приведет к той же ошибке файловой операции, так как адрес будет ссылаться на уже несуществующее окружение фонового процесса.
Если код написан верно, но ошибка повторяется «раз в сто лет», стоит обратить внимание на работу кластера серверов 1С. Выясним возможные технические причины:
rphost), все ссылки во временном хранилище аннулируются.temp операционной системы. Платформа 1С не может прочитать файл с диска сервера, чтобы отдать его клиенту, и выдает ошибку преобразования типа.Подведем итоги нашего исследования. Чтобы навсегда избавиться от ошибки «Значение данного типа невозможно преобразовать для передачи как файл (Неопределено)», придерживайтесь следующих правил:
ЭтаФорма.УникальныйИдентификатор в качестве второго параметра в ПоместитьВоВременноеХранилище.ЭтоАдресВременногоХранилища(Адрес) возвращает истину, это еще не значит, что данные внутри живы. Дополнительно можно проверить наличие данных через ПолучитьИзВременногоХранилища(Адрес) <> Неопределено (но помните, что это лишний серверный вызов).НачатьПолучениеФайлаССервера), но следите за тем, чтобы контекст формы оставался живым до окончания процесса.Соблюдение этих структурных подходов позволит вашим пользователям стабильно сохранять PDF-документы без раздражающих системных ошибок.