#std542¶
Доступ к файловой системе из кода конфигурации¶
1.¶
При обращении к файлам и каталогам из кода конфигурации учитывайте права пользователя ОС, от имени которого запущено приложение.
1.1.¶
Если код выполняется на клиенте, доступ к файловой системе идет под правами пользователя, который запустил приложение (тонкий, толстый или веб-клиент). Обычно это текущий пользователь ОС.
1.2.¶
Если код выполняется на сервере:
- в клиент-серверном варианте доступ ограничен правами пользователя, от имени которого запущен сервер
1С:Предприятия; - в файловом варианте, опубликованном на веб-сервере, доступ ограничен правами пользователя веб-сервера.
Рабочие процессы могут быть запущены от имени пользователя, отличного от пользователя агента сервера.
Подробно: описание служебного файла swpuser.ini.
2.¶
Запрещено записывать файлы в каталог исполняемых файлов платформы, получаемый через КаталогПрограммы().
КаталогПрограммы() допустимо использовать только для чтения или запуска файлов.
Например, в Windows допустим запуск копии тонкого клиента текущей версии:
3.¶
Даже если #std761: локализация конфигурации на другие языки не планируется, обеспечивайте переносимость автоматически сформированных файлов между ОС с разными кодировками.
3.1.¶
В именах файлов, которые формируются системой, используйте только английские буквы и цифры. Для текстовых файлов используйте только UTF-8.
Это особенно важно для macOS.
Ограничение распространяется на файлы обмена, выгрузки, электронные документы и т.п., включая файлы внутри архивов (например, zip).
Исключение: вы не можете повлиять на формат файла (например, формат внешней системы).
3.2.¶
Если имя файла вводит пользователь, разрешайте русскоязычные имена, но дайте возможность транслитерации в латиницу.
По умолчанию, если это не ухудшает UX, предлагайте англоязычное имя файла и UTF-8 для текстовых файлов.
Рекомендации по имени и кодировке разместите в справке в местах, где пользователь сохраняет файлы и выбирает кодировку.
Если конфигурация использует БСП, для транслитерации имен файлов применяйте СтроковыеФункцииКлиентСервер.СтрокаЛатиницей().
Работа с временными файлами и каталогами¶
При работе с временными файлами и каталогами соблюдайте правила ниже.
1.¶
Для получения имени временного файла используйте ПолучитьИмяВременногоФайла() (исключение: веб-клиент, см. п. 3.1).
Иначе возможны:
- ошибки в многопользовательском режиме;
- проблемы с профилями безопасности и правами ОС;
- неконтролируемый рост временных файлов.
Неправильно
У пользователя может не быть прав на запись в каталог, а при одновременном запуске кода из разных сеансов возникнут конфликты.
Если использовать ПолучитьИмяВременногоФайла(), платформа контролирует временные файлы и удаляет их автоматически:
- при перезапуске рабочего процесса (если файл создан на сервере) или клиентского приложения (если файл создан на клиенте);
- через
20минут после серверного вызова или сеанса, где создан файл (клиент-серверный вариант, платформа8.3.17и выше).
Если имя временного файла сформировано другим способом и код его не удалил, файл останется в системе на неопределенное время. В больших базах это создает заметную нагрузку.
Неправильно
Если между созданием и удалением произойдет ошибка, файл останется в каталоге временных файлов.
2.¶
Для временного каталога также используйте имя, полученное через ПолучитьИмяВременногоФайла() (исключение: веб-клиент, см. п. 3.1).
Это обеспечивает уникальность имени в многопользовательском режиме и автоматическое удаление каталога после перезапуска рабочего процесса сервера или клиента. Внутри такого каталога можно создавать подкаталоги и файлы без дополнительных ограничений.
3.1.¶
В веб-клиенте ПолучитьИмяВременногоФайла() недоступен.
Используйте КаталогВременныхФайлов() и УникальныйИдентификатор.
Неправильно
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";
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьФайлЗавершение", ЭтотОбъект);
ПараметрыЗагрузки = ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла();
ПараметрыЗагрузки.ИдентификаторФормы = УникальныйИдентификатор;
ПараметрыЗагрузки.Интерактивно = Ложь;
ФайловаяСистемаКлиент.ЗагрузитьФайл(ОписаниеОповещения,
ПараметрыЗагрузки, ИмяФайлаДляОбработки);
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьФайлЗавершение(ПомещенныйФайл, ДополнительныеПараметры)
...
Результат = ПроизвестиОбработкуНаСервере(Адрес);
...
КонецПроцедуры
См. также¶
- #std700: Установка внешних компонент и расширений платформы
- #std467: Общие требования к конфигурации
Проверки¶
#bslls:FileSystemAccess #bslls:MissingTemporaryFileDeletion #bslls:TempFilesDir