#std542

Доступ к файловой системе из кода конфигурации

1.

При обращении к файлам и каталогам из кода конфигурации учитывайте права пользователя ОС, от имени которого запущено приложение.

1.1.

Если код выполняется на клиенте, доступ к файловой системе идет под правами пользователя, который запустил приложение (тонкий, толстый или веб-клиент). Обычно это текущий пользователь ОС.

1.2.

Если код выполняется на сервере:

  • в клиент-серверном варианте доступ ограничен правами пользователя, от имени которого запущен сервер 1С:Предприятия;
  • в файловом варианте, опубликованном на веб-сервере, доступ ограничен правами пользователя веб-сервера.

Рабочие процессы могут быть запущены от имени пользователя, отличного от пользователя агента сервера. Подробно: описание служебного файла swpuser.ini.

2.

Запрещено записывать файлы в каталог исполняемых файлов платформы, получаемый через КаталогПрограммы().

КаталогПрограммы() допустимо использовать только для чтения или запуска файлов. Например, в Windows допустим запуск копии тонкого клиента текущей версии:

ЗапуститьПриложение(КаталогПрограммы() + "1cv8s.exe");
3.

Даже если #std761: локализация конфигурации на другие языки не планируется, обеспечивайте переносимость автоматически сформированных файлов между ОС с разными кодировками.

3.1.

В именах файлов, которые формируются системой, используйте только английские буквы и цифры. Для текстовых файлов используйте только UTF-8.

Это особенно важно для macOS.

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

3.2.

Если имя файла вводит пользователь, разрешайте русскоязычные имена, но дайте возможность транслитерации в латиницу.

По умолчанию, если это не ухудшает UX, предлагайте англоязычное имя файла и UTF-8 для текстовых файлов.

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

Если конфигурация использует БСП, для транслитерации имен файлов применяйте СтроковыеФункцииКлиентСервер.СтрокаЛатиницей().

Работа с временными файлами и каталогами

При работе с временными файлами и каталогами соблюдайте правила ниже.

1.

Для получения имени временного файла используйте ПолучитьИмяВременногоФайла() (исключение: веб-клиент, см. п. 3.1).

Иначе возможны:

  • ошибки в многопользовательском режиме;
  • проблемы с профилями безопасности и правами ОС;
  • неконтролируемый рост временных файлов.

Неправильно

ИмяПромежуточногоФайла = "C:\Временные файлы 1С\TempFile.xml";
Данные.Записать(ИмяПромежуточногоФайла);

Правильно

ИмяПромежуточногоФайла = ПолучитьИмяВременногоФайла("xml");
Данные.Записать(ИмяПромежуточногоФайла);

У пользователя может не быть прав на запись в каталог, а при одновременном запуске кода из разных сеансов возникнут конфликты.

Если использовать ПолучитьИмяВременногоФайла(), платформа контролирует временные файлы и удаляет их автоматически:

  • при перезапуске рабочего процесса (если файл создан на сервере) или клиентского приложения (если файл создан на клиенте);
  • через 20 минут после серверного вызова или сеанса, где создан файл (клиент-серверный вариант, платформа 8.3.17 и выше).

Если имя временного файла сформировано другим способом и код его не удалил, файл останется в системе на неопределенное время. В больших базах это создает заметную нагрузку.

Неправильно

Каталог = КаталогВременныхФайлов();
ИмяФайла = Строка(Новый УникальныйИдентификатор) + ".xml";
ИмяПромежуточногоФайла = Каталог + ИмяФайла;
Данные.Записать(ИмяПромежуточногоФайла);

Правильно

ИмяПромежуточногоФайла = ПолучитьИмяВременногоФайла("xml");
Данные.Записать(ИмяПромежуточногоФайла);

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

2.

Для временного каталога также используйте имя, полученное через ПолучитьИмяВременногоФайла() (исключение: веб-клиент, см. п. 3.1).

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

3.1.

В веб-клиенте ПолучитьИмяВременногоФайла() недоступен. Используйте КаталогВременныхФайлов() и УникальныйИдентификатор.

Неправильно

Каталог = КаталогВременныхФайлов();
ИмяФайла = "TempDataFile.xml";
ИмяПромежуточногоФайла = Каталог + ИмяФайла;
Данные.Записать(ИмяПромежуточногоФайла);

Правильно

Каталог = КаталогВременныхФайлов();
ИмяФайла = Строка(Новый УникальныйИдентификатор) + ".xml";
ИмяПромежуточногоФайла = Каталог + ИмяФайла;
Данные.Записать(ИмяПромежуточногоФайла);
3.2.

Если в конфигурацию встроена БСП, для создания временных каталогов на клиенте используйте ФайловаяСистемаКлиент.СоздатьВременныйКаталог().

4.

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

ИмяПромежуточногоФайла = ПолучитьИмяВременногоФайла("xml");
Данные.Записать(ИмяПромежуточногоФайла);

// Работа с файлом
...

// Удаляем временный файл
Попытка
    УдалитьФайлы(ИмяПромежуточногоФайла);
Исключение
    ЗаписьЖурналаРегистрации(НСтр("ru = 'Мой механизм.Действие'"), УровеньЖурналаРегистрации.Ошибка, , ,
        ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Проверки

#v8cs:missing-temporary-file-deletion

См. также

#std498: Использование Журнала регистрации.

5.

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

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

5.1.

В редких случаях временные файлы нужно передавать между сеансами (например, подготовка данных для фонового задания или длительный процесс из нескольких вызовов web-сервиса).

Тогда обеспечьте:

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

Передача файлов между клиентом и сервером

1.

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

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

Неправильно

&НаКлиенте
Процедура ОбработатьФайл()
    ...
    ИмяФайла = "C:\Файлы для обработки\Загрузка.xml";
    Результат = ПроизвестиОбработкуНаСервере(ИмяФайла);
    ...
КонецПроцедуры

&НаСервере
Функция ПроизвестиОбработкуНаСервере(ИмяФайла)
    Чтение = Новый ЧтениеТекста(ИмяФайла);
    ...
    Результат = Чтение.Прочитать();
    Возврат Результат;
КонецФункции

Правильно

&НаКлиенте
Процедура ОбработатьФайл()
    ...
    ИмяФайлаДляОбработки = "C:\Файлы для обработки\Загрузка.xml";
    ОписаниеОповещения = Новый ОписаниеОповещения(
        "ОбработатьФайлЗавершение", ЭтотОбъект);
    НачатьПомещениеФайла(ОписаниеОповещения,,
        ИмяФайлаДляОбработки, Ложь,
        УникальныйИдентификатор);
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьФайлЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)
    ...
    Результат = ПроизвестиОбработкуНаСервере(Адрес);
    ...
КонецПроцедуры

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

Если данные файла должны храниться между несколькими серверными вызовами, при помещении в хранилище передавайте УникальныйИдентификаторФормы в ПоместитьФайл().

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

Неправильно

&НаКлиенте
Процедура ОбработатьФайл()
    ...
    // Первый серверный вызов
    ИмяФайлаДляОбработки = "C:\Файлы для обработки\Загрузка.xml";
    ОписаниеОповещения = Новый ОписаниеОповещения(
        "ОбработатьФайлЗавершение", ЭтотОбъект);
    НачатьПомещениеФайла(ОписаниеОповещения,,
        ИмяФайлаДляОбработки, Ложь,
        УникальныйИдентификатор);
    ...
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьФайлЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)
    ...
    Результат = ПроизвестиНачальнуюОбработкуНаСервере(Адрес);
    ПродолжитьОбработкуФайла();
    ...
КонецПроцедуры

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

&НаКлиенте
Процедура ПродолжитьОбработкуФайлаЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)
    ...
    Результат = ПроизвестиКонечнуюОбработкуНаСервере(Адрес);
    ...
КонецПроцедуры

Правильно

&НаКлиенте
Процедура ОбработатьФайл()
    ...
    // Первый серверный вызов
    ИмяФайлаДляОбработки = "C:\Файлы для обработки\Загрузка.xml";
    ОписаниеОповещения = Новый ОписаниеОповещения(
        "ОбработатьФайлЗавершение", ЭтотОбъект);
    НачатьПомещениеФайла(ОписаниеОповещения,,
        ИмяФайлаДляОбработки, Ложь,
        УникальныйИдентификатор);
    ...
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьФайлЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)
    ...
    Результат = ПроизвестиНачальнуюОбработкуНаСервере(Адрес);
    ПродолжитьОбработкуФайла();
    ...
КонецПроцедуры

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

&НаКлиенте
Процедура ПродолжитьОбработкуФайлаЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры)
    ...
    Результат = ПроизвестиКонечнуюОбработкуНаСервере(Адрес);
    ...
КонецПроцедуры

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

3.

Если в конфигурацию встроена БСП, для помещения файлов во временное хранилище используйте ЗагрузитьФайл() и ЗагрузитьФайлы() общего модуля ФайловаяСистемаКлиент.

Чтобы сохранить данные файла между несколькими серверными вызовами, используйте свойство ИдентификаторФормы параметра ПараметрыЗагрузки.

&НаКлиенте
Процедура ОбработатьФайл()
    ...
    ИмяФайлаДляОбработки = "C:\Файлы для обработки\Загрузка.xml";
    ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьФайлЗавершение", ЭтотОбъект);

    ПараметрыЗагрузки = ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла();
    ПараметрыЗагрузки.ИдентификаторФормы = УникальныйИдентификатор;
    ПараметрыЗагрузки.Интерактивно = Ложь;

    ФайловаяСистемаКлиент.ЗагрузитьФайл(ОписаниеОповещения,
        ПараметрыЗагрузки, ИмяФайлаДляОбработки);
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьФайлЗавершение(ПомещенныйФайл, ДополнительныеПараметры)
    ...
    Результат = ПроизвестиОбработкуНаСервере(Адрес);
    ...
КонецПроцедуры
См. также
Проверки

#bslls:FileSystemAccess #bslls:MissingTemporaryFileDeletion #bslls:TempFilesDir

#acc:441 #acc:495

Источник

https://its.1c.ru/db/v8std#content:542