Почему в 1С Форматированный документ выдает ошибку «can't read file» при чтении из Хранилища значения?

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

Работа с объектом ФорматированныйДокумент часто преподносит сюрпризы разработчикам, особенно когда дело касается длительного хранения данных в базе. Одной из наиболее неприятных ситуаций является ошибка «can't read file» или появление пустого окна вместо ожидаемого текста с картинками. Проанализируем, почему это происходит, и разберем по шагам, как обеспечить стабильную работу этого механизма.

Суть проблемы и механизм возникновения ошибки

Рассмотрим стандартную ситуацию: в конфигурации реализован регистр сведений, где один из реквизитов имеет тип ХранилищеЗначения. В этот реквизит мы записываем содержимое ФорматированныйДокумент. При первом открытии формы в рамках сеанса данные отображаются корректно, но при повторном обращении (особенно через обработчик ожидания или при обновлении данных) платформа выдает ошибку «can't read file».

Выясним причину такого поведения. Внутри платформы 1С ФорматированныйДокумент не является просто строкой. Для его отображения на форме платформа генерирует временный HTML-файл, который затем загружается во встроенный компонент браузера (в современных версиях это WebKit). Когда мы помещаем объект в ХранилищеЗначения, происходит его сериализация.

Критический момент: При повторном извлечении объекта из хранилища платформа может пытаться использовать ссылки на временные файлы, которые были созданы в предыдущем цикле обращения к объекту. Если операционная система или сама платформа уже очистили папку временных файлов, а объект в памяти продолжает ссылаться на старый путь — возникает ошибка доступа к файлу.

Решение №1: Явная инициализация объекта перед загрузкой

Проанализируем самый простой способ «лечения» данной проблемы. Зачастую разработчики просто присваивают полученное из хранилища значение реквизиту формы. Однако для стабильной работы ФорматированныйДокумент на форме лучше предварительно «сбросить» его состояние.

Посмотрим на пример правильного кода при получении данных на сервере:


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

    Если Выборка.Выбран() Тогда
        // ВАЖНО: Инициализируем реквизит формы новым объектом
        Объект.ОписаниеФД = Новый ФорматированныйДокумент();
        
        // Только после этого извлекаем данные из хранилища
        ДанныеИзХранилища = Выборка.ОписаниеХранилище.Получить();
        
        Если ТипЗнч(ДанныеИзХранилища) = Тип("ФорматированныйДокумент") Тогда
            Объект.ОписаниеФД = ДанныеИзХранилища;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

Решение №2: Отказ от хранения объекта в пользу HTML и картинок

Опытные разработчики 1С рекомендуют не хранить сам объект ФорматированныйДокумент напрямую в ХранилищеЗначения. Это связано с тем, что формат сериализации этого объекта может меняться от версии к версии платформы, а внутренние ссылки на ресурсы (картинки) вида v8res:// крайне нестабильны.

Разберем более надежный алгоритм работы:

  1. При записи получаем из документа текст HTML и структуру картинок.
  2. Сохраняем в ХранилищеЗначения структуру, содержащую эти два элемента.
  3. При чтении восстанавливаем объект методом УстановитьHTML().

Рассмотрим пример реализации записи:


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

И пример восстановления данных при чтении:


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

Этот метод считается эталонным, так как он полностью обходит механизмы кэширования самой платформы и полагается только на чистые данные HTML.

Проблема «засыпания» WebKit в фоновых процессах

Если вы используете ПодключитьОбработчикОжидания для автоматического обновления форматированного документа (например, раз в 30 секунд), вы можете столкнуться с тем, что окно становится пустым. Это происходит из-за оптимизации движка отрисовки: если элемент управления не в фокусе или форма не активна, WebKit может остановить рендеринг.

Чтобы этого избежать, после программного обновления данных рекомендуется вызвать метод формы ОбновитьОтображениеДанных(). В некоторых случаях помогает кратковременное изменение видимости элемента или его размеров, что заставляет графическую подсистему «проснуться».

Влияние расширений и кэша пользователя

Если ваш реквизит ХранилищеЗначения добавлен через расширение конфигурации, проанализируем еще один нюанс. Иногда при десериализации объектов из расширений платформа теряет типы внутренних коллекций. Если ошибка «can't read file» сохраняется, попробуйте временно перенести реквизит в основную конфигурацию для проверки.

Также не забывайте о возможности очистки локального кэша 1С. Ошибка может быть вызвана повреждением локальных файлов в каталоге %AppData%\Local\1C\1cv8\. Если после удаления этих папок проблема исчезает (пусть и временно) — значит, корень зла именно в механизме работы платформы с временными файлами отображения HTML.

Подведем итог: Для стабильной работы всегда используйте метод сохранения пары HTML + Картинки вместо сохранения объекта целиком. Это избавит вас от большинства проблем с отображением в управляемых формах.

← На главную