К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как сохранить файл в каталог временных файлов 1С

Как сохранить файл в каталог временных файлов 1С: функции КаталогВременныхФайлов и ПолучитьИмяВременногоФайла, примеры кода, тонкий и веб-клиент, типовые ошибки.

Работа с временными файлами — типовая задача при разработке на платформе 1С:Предприятие: выгрузка отчёта перед отправкой по почте, промежуточный XML при обмене данными, распаковка архива, полученного из веб-сервиса. Платформа предоставляет встроенные средства, которые избавляют от необходимости вручную прописывать пути к системным папкам Windows или Linux и гарантируют корректную работу на разных клиентах.

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

Важно понимать контекст исполнения: на сервере 1С временный каталог расположен на сервере, на клиенте — на машине пользователя. Файл, сохранённый в серверном временном каталоге, недоступен пользователю напрямую — его нужно либо передать на клиент через временное хранилище, либо пересоздать на клиенте.

Какие функции платформы отвечают за временные файлы

Функция КаталогВременныхФайлов() возвращает строку — путь к каталогу временных файлов операционной системы для текущего сеанса. На Windows это обычно подкаталог внутри профиля пользователя (например, в %TEMP%), на Linux — каталог вроде /tmp или выделенный каталог сервера 1С. Путь всегда заканчивается разделителем каталога, поэтому имя файла можно присоединять простой конкатенацией.

Функция ПолучитьИмяВременногоФайла(Расширение) делает шаг дальше: она генерирует уникальное имя файла внутри временного каталога и возвращает полный путь. Параметр задаёт расширение — например, "xml", "zip", "txt". Если расширение не указано, файл получит расширение tmp. Важный нюанс: функция не только формирует имя, но и создаёт пустой файл на диске, поэтому вызовы в цикле без последующего удаления приводят к накоплению мусора.

Обе функции доступны и на сервере, и на толстом/тонком клиенте. В веб-клиенте прямой доступ к файловой системе ограничен, и там применяется другой сценарий, описанный ниже.

Как сохранить один файл через ПолучитьИмяВременногоФайла

Самый короткий сценарий — получить готовое уникальное имя и записать в него содержимое. Подходит для текстовых выгрузок, XML, JSON и двоичных данных.

ИмяФайла = ПолучитьИмяВременногоФайла("xml");

Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);

Запись.Записать(ТекстВыгрузки);

Запись.Закрыть();

// ... использование файла ...

УдалитьФайлы(ИмяФайла);

Для двоичных данных (картинки, архивы, данные из хранилища значений) вместо ЗаписьТекста используется метод Записать() объекта ДвоичныеДанные:

ИмяФайла = ПолучитьИмяВременногоФайла("zip");

ДвоичныеДанные.Записать(ИмяФайла);

Признак успешного выполнения — файл существует и имеет ненулевой размер. Проверить это можно объектом Файл: создать его с именем файла, вызвать Существует() и прочитать свойство Размер().

bsl
ИмяФайла = ПолучитьИмяВременногоФайла("txt");
Запись = Новый ЗаписьТекста(ИмяФайла);
Запись.ЗаписатьСтроку("Данные выгрузки");
Запись.Закрыть();
УдалитьФайлы(ИмяФайла);

Как работать с каталогом временных файлов напрямую

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

БазовыйКаталог = КаталогВременныхФайлов();

РабочийКаталог = БазовыйКаталог + "exchange_" + Строка(Новый УникальныйИдентификатор) + "\";

СоздатьКаталог(РабочийКаталог);

ИмяФайла = РабочийКаталог + "data.xml";

// запись файла ...

УдалитьФайлы(РабочийКаталог);

Обратите внимание на разделитель пути: на Windows это обратный слэш, на Linux — прямой. Чтобы код был переносимым, не зашивайте символ в строки, а берите его из объекта Файл или используйте конструкции, которые платформа нормализует сама. На практике платформа часто корректно обрабатывает оба разделителя, но явная аккуратность избавляет от ошибок при переносе решения на Linux-сервер.

Порядок действий
  1. 1
    Вызовите КаталогВременныхФайлов() и сохраните путь в переменную
  2. 2
    Сформируйте имя подкаталога с уникальным идентификатором
  3. 3
    Создайте каталог через СоздатьКаталог()
  4. 4
    Запишите нужные файлы внутрь подкаталога
  5. 5
    После обработки удалите подкаталог целиком через УдалитьФайлы()

Различия сервера, тонкого клиента и веб-клиента

Контекст исполнения определяет, где физически окажется файл. Код, выполняемый в серверной процедуре, пишет во временный каталог сервера 1С — пользователь этот файл не увидит. Код на клиенте пишет в каталог временных файлов компьютера пользователя.

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

В веб-клиенте прямая запись в файловую систему недоступна без расширения работы с файлами. Там применяют НачатьПомещениеФайла/НачатьПолучениеФайлов и методы работы с временным хранилищем, а понятие «каталог временных файлов» для пользователя фактически заменяется стандартным диалогом скачивания браузера.

Очистка и время жизни временных файлов

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

Правильный шаблон — оборачивать работу с файлом в попытку/исключение и удалять файл в блоке, который выполнится всегда:

ИмяФайла = ПолучитьИмяВременногоФайла("xml");

Попытка

// запись и обработка файла

Исключение

// обработка ошибки

КонецПопытки;

УдалитьФайлы(ИмяФайла);

Если обработка прерывается по ошибке до удаления, файл всё равно желательно удалить — для этого удаление размещают после блока обработки, а не только в ветке успеха. Удаление несуществующего файла через УдалитьФайлы ошибки не вызывает, поэтому повторный вызов безопасен.

Типичные ошибки и как их избежать

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

Вторая группа ошибок связана с именами: ручная генерация имён вида «temp1.xml» приводит к коллизиям при параллельных сеансах, когда два пользователя перезаписывают файл друг друга. Используйте ПолучитьИмяВременногоФайла или уникальный идентификатор в имени. Третья типичная ситуация — отсутствие удаления файлов в циклических обработках, из-за чего за ночь пакетная выгрузка создаёт тысячи файлов.

Типичные ошибки
01
Чтение серверного временного файла на клиенте по пути — файл недоступен, нужна передача через временное хранилище
02
Фиксированные имена файлов — коллизии при параллельной работе пользователей
03
Отсутствие УдалитьФайлы() — переполнение диска сервера при регламентных обработках
04
Потеря расширения — ПолучитьИмяВременногоФайла() без параметра даёт .tmp, и сторонние программы не распознают формат
05
Зашитый в код разделитель пути — ошибки при переносе решения между Windows и Linux

Как проверить результат и выбрать подход

После записи убедитесь, что файл действительно создан и содержит данные. Минимальная проверка — существование и размер; для текстовых форматов полезно дополнительно прочитать начало файла и сверить с ожидаемой структурой (например, наличие XML-декларации).

Контрольные точки

Как проверить результат

Существование файла
Норма

Файл.Существует() возвращает Истина

Тревожный признак

Файла нет — проверьте контекст исполнения (сервер/клиент) и права на каталог

Размер файла
Норма

Размер больше нуля и соответствует объёму данных

Тревожный признак

Нулевой размер — запись не выполнена или поток не закрыт

Содержимое
Норма

Первая строка соответствует ожидаемому формату

Тревожный признак

Кракозябры — неверная кодировка при записи

Очистка
Норма

После УдалитьФайлы файл отсутствует

Тревожный признак

Файл остался — удаление не вызывалось или файл заблокирован другим процессом

Выбор между двумя функциями прост: один файл с уникальным именем — ПолучитьИмяВременногоФайла; несколько файлов или структура каталогов — КаталогВременныхФайлов плюс собственный подкаталог. Для передачи пользователю результата, сформированного на сервере, всегда добавляйте этап с временным хранилищем.

Маршрут решения

Как выбрать действие

Нужен один файл для промежуточной обработкиВызовите ПолучитьИмяВременногоФайла с нужным расширением и запишите данные
Нужно распаковать архив или сохранить группу файловСоздайте уникальный подкаталог внутри КаталогВременныхФайлов()
Файл сформирован на сервере и нужен пользователюПоместите двоичные данные во временное хранилище и передайте адрес на клиент
Работа идёт в веб-клиентеИспользуйте НачатьПолучениеФайлов или диалог сохранения вместо прямой записи на диск
Итог

Что важно запомнить

ПолучитьИмяВременногоФайла даёт готовое уникальное имя, КаталогВременныхФайлов — путь для собственной структуры папок. Учитывайте контекст сервер/клиент, передавайте данные между ними через временное хранилище и всегда удаляйте временные файлы после использования.

Частые вопросы

Чем КаталогВременныхФайлов() отличается от ПолучитьИмяВременногоФайла()?

Первая функция возвращает только путь к каталогу, имя файла вы формируете сами. Вторая сразу генерирует уникальное полное имя и создаёт пустой файл с заданным расширением. Для одиночного файла удобнее вторая, для группы файлов — первая.

Почему файл, созданный на сервере, не виден на клиенте?

Временный каталог сервера находится на серверной машине, а клиент обращается к своей локальной файловой системе. Передайте содержимое через ПоместитьВоВременноеХранилище и ПолучитьИзВременногоХранилища, а не путь к файлу.

Нужно ли удалять временные файлы вручную?

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

Как задать правильное расширение временного файла?

Передайте расширение параметром: ПолучитьИмяВременногоФайла("xlsx"). Без параметра файл получит расширение tmp, и внешние программы (Excel, архиватор) не смогут корректно его открыть по ассоциации.

Работает ли запись во временный каталог в веб-клиенте?

Прямая запись в файловую систему в веб-клиенте ограничена. Используйте временное хранилище и асинхронные методы получения файлов, а пользователю результат отдавайте через стандартный механизм скачивания браузера.

Что делать, если временный файл не удаляется?

Чаще всего файл заблокирован незакрытым объектом записи или чтения — убедитесь, что вызван Закрыть() у ЗаписьТекста/ЧтениеXML. Также проверьте, что файл не открыт внешней программой, и что удаление выполняется в том же контексте (сервер/клиент), где файл создавался.