#std542¶
Доступ к файловой системе из кода конфигурации¶
Работа с временными файлами и каталогами¶
1.¶
При работе с временными файлами и каталогами соблюдайте правила ниже.
1.1.¶
Для получения имени временного файла используйте ПолучитьИмяВременногоФайла() (исключение: веб-клиент, см. п. 1.3).
Иначе возможны:
- ошибки в многопользовательском режиме;
- проблемы с профилями безопасности и правами ОС;
- неконтролируемый рост временных файлов.
Неправильно
У пользователя может не быть прав на запись в каталог, а при одновременном запуске кода из разных сеансов возникнут конфликты.
Если использовать ПолучитьИмяВременногоФайла(), платформа гарантирует уникальность имени, сохраняет контроль над файлом и удаляет его автоматически:
- при перезапуске рабочего процесса (если файл создан на сервере) или клиентского приложения (если файл создан на клиенте);
- через
20минут после серверного вызова или сеанса, где создан файл (платформа8.3.17и выше).
Если имя временного файла сформировано другим способом и код его не удалил, файл останется в системе на неопределенное время. В больших базах это создает заметную нагрузку.
Неправильно
Если между созданием и удалением произойдет ошибка, файл останется в каталоге временных файлов.
1.2.¶
Для временного каталога также используйте имя, полученное через ПолучитьИмяВременногоФайла() (исключение: веб-клиент, см. п. 1.3).
Это обеспечивает уникальность имени в многопользовательском режиме и автоматическое удаление каталога после перезапуска рабочего процесса сервера или клиента. Внутри такого каталога можно создавать подкаталоги и файлы без дополнительных ограничений.
1.3.¶
В веб-клиенте ПолучитьИмяВременногоФайла() недоступен.
Используйте КаталогВременныхФайлов() и УникальныйИдентификатор.
Неправильно
Если в конфигурацию встроена БСП, для создания временных каталогов на клиенте используйте ФайловаяСистемаКлиент.СоздатьВременныйКаталог().
В стандарте не указано
Чтобы веб-клиент вообще мог создавать файлы и каталоги на компьютере пользователя, нужно расширение работы с файлами. Без него код доступа к файловой системе на клиенте не заработает, а установка расширения требует действий пользователя и поддерживается не во всех браузерах.
Поэтому лучше вообще избегать сценариев, где из веб-клиента нужно что-то создавать в файловой системе. Формируйте данные в памяти или на сервере и отдавайте пользователю готовый файл.
1.4.¶
После завершения работы временный файл или каталог удаляйте явно. Нельзя рассчитывать только на удаление при следующем запуске платформы: это может привести к исчерпанию свободного места.
ИмяПромежуточногоФайла = ПолучитьИмяВременногоФайла("xml");
Данные.Записать(ИмяПромежуточногоФайла);
// Работа с файлом
...
// Удаляем временный файл
Попытка
УдалитьФайлы(ИмяПромежуточногоФайла);
Исключение
ЗаписьЖурналаРегистрации(НСтр("ru = 'Мой механизм.Действие'"), УровеньЖурналаРегистрации.Ошибка, , ,
ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Если в конфигурацию встроена БСП, используйте ФайловаяСистема.УдалитьВременныйФайл() и ФайловаяСистема.УдалитьВременныйКаталог().
См. также¶
#std498: Использование Журнала регистрации.
1.5.¶
Если временные файлы или каталоги используются на сервере, завершайте работу с ними в рамках одного серверного вызова.
В кластере следующий вызов может выполниться на другом компьютере, и файл станет недоступен.
Если данные должны жить между серверными вызовами в рамках одного сеанса, используйте временное хранилище платформы (ПоместитьВоВременноеХранилище(), ПолучитьИзВременногоХранилища()).
1.6.¶
В редких случаях временные файлы нужно передавать между сеансами (например, подготовка данных для фонового задания или длительный процесс из нескольких вызовов web-сервиса).
Тогда обеспечьте:
- общее место хранения, доступное всем серверам кластера;
- регистрацию имен файлов и времени создания во вспомогательном регистре сведений;
- удаление файлов и записей при штатном завершении процесса;
- регламентную очистку просроченных файлов и записей при аварийных сценариях.
Если в конфигурацию встроена БСП, для общего места хранения используйте ФайловаяСистема.ОбщийКаталогВременныхФайлов().
Работа с двоичными данными и потоками¶
2.¶
Обращение к файловой системе ради получения двоичных данных обычно избыточно: двоичные данные объекта в любом случае размещаются в памяти.
2.1.¶
Для получения двоичных данных объектов используйте потоки в памяти: ПотокВПамяти, ЗаписьДанных, ЧтениеДанных.
Неправильно
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt");
ТекстИнформации = Новый ТекстовыйДокумент;
ТекстИнформации.УстановитьТекст(ТехнологическаяИнформация);
ТекстИнформации.Записать(ИмяВременногоФайла, КодировкаТекста.UTF8);
Результат = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяВременногоФайла),
Новый УникальныйИдентификатор);
УдалитьФайлы(ИмяВременногоФайла);
Правильно
ПотокФайла = Новый ПотокВПамяти;
ТекстИнформации = Новый ТекстовыйДокумент;
ТекстИнформации.УстановитьТекст(ТехнологическаяИнформация);
ТекстИнформации.Записать(ПотокФайла, КодировкаТекста.UTF8);
Результат = ПоместитьВоВременноеХранилище(ПотокФайла.ЗакрытьИПолучитьДвоичныеДанные(),
Новый УникальныйИдентификатор);
2.2.¶
После чтения двоичных данных закрывайте поток. Иначе возможны утечка памяти и невозможность дальнейшей работы.
2.3.¶
Файловая система для получения двоичных данных допустима, только если особенности платформы не позволяют получить двоичные данные объекта в памяти и остается единственный путь: запись во временный файл и получение его двоичных данных.
Передача файлов между клиентом и сервером¶
3.¶
Если один и тот же файл обрабатывается и на клиенте, и на сервере, передавайте его через временное хранилище. Клиент и серверы кластера — разные компьютеры с разными файловыми системами, поэтому прямой путь к файлу ненадежен.
Неправильно
&НаКлиенте
Процедура ОбработатьФайл()
...
ИмяФайла = "C:\Файлы для обработки\Загрузка.xml";
Результат = ПроизвестиОбработкуНаСервере(ИмяФайла);
...
КонецПроцедуры
&НаСервере
Функция ПроизвестиОбработкуНаСервере(ИмяФайла)
Чтение = Новый ЧтениеТекста(ИмяФайла);
...
Результат = Чтение.Прочитать();
Возврат Результат;
КонецФункции
Правильно
&НаКлиенте
Процедура ПродолжитьОбработкуФайла(Адрес)
...
// Адрес во временном хранилище получен при помещении файла на сервер, см. п. 3.1
Результат = ПроизвестиОбработкуНаСервере(Адрес);
...
КонецПроцедуры
&НаСервере
Функция ПроизвестиОбработкуНаСервере(Адрес)
Данные = ПолучитьИзВременногоХранилища(Адрес);
ИмяПромежуточногоФайла = ПолучитьИмяВременногоФайла("txt");
Данные.Записать(ИмяПромежуточногоФайла);
Чтение = Новый ЧтениеТекста(ИмяПромежуточногоФайла);
...
Результат = Чтение.Прочитать();
...
УдалитьФайлы(ИмяПромежуточногоФайла);
Возврат Результат;
КонецФункции
3.1.¶
Для загрузки файла с клиента на сервер используйте ПоместитьФайлНаСерверАсинх(), ПоместитьФайлыНаСерверАсинх(), НачатьПомещениеФайлаНаСервер(), НачатьПомещениеФайловНаСервер().
В стандарте не указано
Эти методы появились в платформе 8.3.15 и заменяют ПоместитьФайл(), ПоместитьФайлы(), НачатьПомещениеФайла(), НачатьПомещениеФайлов().
Если данные файла должны храниться между несколькими серверными вызовами, передавайте в эти методы идентификатор текущей формы (параметр УникальныйИдентификаторФормы).
Такие данные удаляются из временного хранилища только при закрытии формы.
При повторном помещении того же файла предыдущее значение удаляйте вручную через УдалитьИзВременногоХранилища().
Иначе в хранилище останутся две копии файла: адрес первой копии будет потерян, что приведет к лишнему расходу ресурсов и замедлению работы.
Если в конфигурацию встроена БСП, используйте ФайловаяСистемаКлиент.ЗагрузитьФайл() и ФайловаяСистемаКлиент.ЗагрузитьФайлы().
Чтобы сохранить данные файла между несколькими серверными вызовами, заполните свойство ИдентификаторФормы параметра ПараметрыЗагрузки.
Описание помещенного файла, включая адрес во временном хранилище, придет в обработчик оповещения.
&НаКлиенте
Процедура ОбработатьФайл()
...
ИмяФайлаДляОбработки = "C:\Файлы для обработки\Загрузка.xml";
ОписаниеОповещения = Новый ОписаниеОповещения("ОбработатьФайлЗавершение", ЭтотОбъект);
ПараметрыЗагрузки = ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла();
ПараметрыЗагрузки.ИдентификаторФормы = УникальныйИдентификатор;
ПараметрыЗагрузки.Интерактивно = Ложь;
ФайловаяСистемаКлиент.ЗагрузитьФайл(ОписаниеОповещения,
ПараметрыЗагрузки, ИмяФайлаДляОбработки);
КонецПроцедуры
&НаКлиенте
Процедура ОбработатьФайлЗавершение(ОписаниеПомещенногоФайла, ДополнительныеПараметры)
Если ОписаниеПомещенногоФайла = Неопределено Тогда
// Пользователь отказался от помещения файла
Возврат;
КонецЕсли;
...
КонецПроцедуры
3.2.¶
Для сохранения (скачивания) файла сервера на клиенте используйте ПолучитьФайлССервераАсинх(), ПолучитьФайлыССервераАсинх(), НачатьПолучениеФайлаССервера(), НачатьПолучениеФайловССервера().
Если в конфигурацию встроена БСП, используйте ФайловаяСистемаКлиент.СохранитьФайл() и ФайловаяСистемаКлиент.СохранитьФайлы().
Совместимость имен файлов¶
4.¶
Даже если #std761: локализация конфигурации на другие языки не планируется, обеспечивайте переносимость автоматически сформированных файлов между ОС с разными кодировками.
4.1.¶
В именах файлов, которые формируются системой, используйте только английские буквы и цифры. Для текстовых файлов используйте только UTF-8.
Это особенно важно для macOS.
Ограничение распространяется на файлы обмена, выгрузки, электронные документы и т.п., включая файлы внутри архивов (например, zip).
Исключение: вы не можете повлиять на формат файла (например, формат внешней системы).
4.2.¶
Если имя файла вводит пользователь, разрешайте русскоязычные имена, но дайте возможность транслитерации в латиницу.
По умолчанию, если это не ухудшает UX, предлагайте англоязычное имя файла и UTF-8 для текстовых файлов.
Рекомендации по имени и кодировке разместите в справке в местах, где пользователь сохраняет файлы и выбирает кодировку.
Если конфигурация использует БСП, для транслитерации имен файлов применяйте СтроковыеФункцииКлиентСервер.СтрокаЛатиницей().
Права доступа к файлам¶
5.¶
При обращении к файлам и каталогам из кода конфигурации учитывайте права пользователя ОС, от имени которого запущено приложение.
5.1.¶
Если код выполняется на клиенте, доступ к файловой системе идет под правами пользователя, который запустил приложение (тонкий, толстый или веб-клиент). Обычно это текущий пользователь ОС.
5.2.¶
Если код выполняется на сервере:
- в клиент-серверном варианте доступ ограничен правами пользователя, от имени которого запущен сервер
1С:Предприятия; - в файловом варианте, опубликованном на веб-сервере, доступ ограничен правами пользователя веб-сервера.
Рабочие процессы могут быть запущены от имени пользователя, отличного от пользователя агента сервера.
Подробно: описание служебного файла swpuser.ini.
Безопасность файловой системы¶
6.¶
Код конфигурации не должен читать и изменять файлы, не предусмотренные проектным решением. Иначе возможны несанкционированный доступ к данным и нарушение работы ОС.
6.1.¶
Запрещено хранить путь или имя файла в реквизитах формы: на клиенте их можно подменить сторонними средствами, и серверный код прочитает или изменит произвольный файл.
Служебные реквизиты объекта пользователь напрямую изменить не может, но они попадают в данные формы (в основной реквизит Объект).
Для них при записи на сервере проверяйте, что значение не изменили на клиенте.
6.2.¶
Запрещено передавать путь к файлу в параметры серверных процедур форм и экспортных процедур серверных общих модулей. Такие процедуры можно вызвать с клиента сторонними средствами.
6.3.¶
Если серверный метод использует расширение файла, переданное с клиента, проверяйте его одним из способов:
- опишите на сервере коллекцию допустимых расширений и проверяйте вхождение переданного значения в нее;
- используйте
ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла()из БСП.
6.4.¶
Если путь к файлу формируется по данным из информационной базы (например, по полю ввода, которое редактирует пользователь), используйте ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла() из БСП.
6.5.¶
Перед работой с файлом на сервере убедитесь, что файл находится во временном каталоге или другом специально предусмотренном месте.
Пример 1
Пример 2
6.6.¶
При работе с временными файлами убедитесь, что выполняются условия:
- вся работа с файлом идет в рамках одной процедуры;
- путь к файлу получен методом
ПолучитьИмяВременногоФайла()и не изменяется; - после использования файл на диске удаляется.
6.7.¶
Запрещено записывать файлы в каталог исполняемых файлов платформы, получаемый через КаталогПрограммы().
КаталогПрограммы() допустимо использовать только для чтения или запуска файлов.
Сам запуск выполняйте по правилам #std774: Безопасность запуска приложений.
6.8.¶
Администраторам информационных баз рекомендуется ограничивать доступ к файловой системе на сервере профилями безопасности.
См. также¶
- #std700: Установка внешних компонент и расширений платформы
- #std467: Общие требования к конфигурации
- #std794: Ограничения на использование внешних ресурсов