При выгрузке отчетов или печатных форм в файлы форматов Word (DOCX) или Excel разработчики нередко сталкиваются с ошибкой: «Ошибка доступа к файлу... 5(0x00000005): Отказано в доступе». Ситуация часто ставит в тупик тем, что в тестовой файловой базе выгрузка проходит без замечаний, а в клиент-серверном режиме завершается аварийно, даже если текущий пользователь системы 1С обладает полными административными правами.
Проанализируем природу этой ошибки в клиент-серверной архитектуре и разберем архитектурно правильные способы ее устранения.
Посмотрим на типичный фрагмент кода, приводящий к сбою на стороне сервера:
ТабДок.Записать(ПутьКФайлам + Стр.Контрагент + ".docx", ТипФайлаТабличногоДокумента.DOCX);
Если этот код выполняется внутри серверной процедуры (директива &НаСервере или общий модуль с признаком «Сервер»), в процессе сохранения возникают сразу две ключевые проблемы:
C:\Users\Admin2C\Desktop\..., переданный с клиента на сервер, указывает вовсе не на компьютер пользователя. Сервер приложений пытается записать документ на локальный диск самого физического сервера, где папки текущего пользователя может вовсе не существовать. Кроме того, службы Windows изолированы (Session 0 Isolation) и не имеют доступа к пользовательским рабочим столам.usr1cv8). Какими бы правами ни обладал интерактивный пользователь в 1С или на своем локальном компьютере, служба кластера серверов 1С ограничена собственными правами NTFS. По умолчанию запись в пользовательские профили C:\Users\ для учетной записи usr1cv8 заблокирована.Самое быстрое и распространенное решение — формировать табличный документ на сервере, а саму запись в файл выполнять на клиенте. Клиентское приложение запущено от имени локального пользователя, имеет полный доступ к его рабочему столу и локальным папкам.
Разберем по шагам реализацию этого подхода в управляемой форме. На сервере мы только генерируем данные, а метод Записать() вызываем в процедуре &НаКлиенте:
&НаСервере
Функция СформироватьТабличныйДокументНаСервере()
ТабДок = Новый ТабличныйДокумент;
// Заполнение макета и табличного документа данными
Возврат ТабДок;
КонецФункции
&НаКлиенте
Процедура СохранитьДокументВWord()
ТабДок = СформироватьТабличныйДокументНаСервере();
// Путь к файлу на компьютере пользователя
ПолноеИмяФайла = "C:\Users\Admin2C\Desktop\Отчет.docx";
ТабДок.Записать(ПолноеИмяФайла, ТипФайлаТабличногоДокумента.DOCX);
ПоказатьОповещениеПользователя("Успешно", , "Файл сохранен на рабочий стол");
КонецПроцедуры
В этом сценарии ресурсоемкое построение документа выполняется мощностями сервера, а клиент лишь выполняет операцию сохранения готового объекта в локальный файл.
Если процедура формирования отчета работает в рамках общего сервисного механизма, где документ сразу преобразуется в бинарные данные, правильнее использовать временное хранилище платформы. Рассмотрим этот вариант:
ПолучитьИмяВременногоФайла(). К этой системной директории у службы сервера гарантированно есть доступ.ПоместитьВоВременноеХранилище().Посмотрим на пример реализации:
&НаСервере
Функция СформироватьИПоместитьФайлВХранилище()
ТабДок = Новый ТабличныйДокумент;
// Заполнение макета
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("docx");
ТабДок.Записать(ИмяВременногоФайла, ТипФайлаТабличногоДокумента.DOCX);
ДвоичныеДанные = Новый ДвоичныеДанные(ИмяВременногоФайла);
АдресФайла = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
УдалитьФайлы(ИмяВременногоФайла);
Возврат АдресФайла;
КонецФункции
&НаКлиенте
Процедура СохранитьЧерезХранилище()
АдресФайла = СформироватьИПоместитьФайлВХранилище();
ПутьСохранения = "C:\Users\Admin2C\Desktop\Отчет.docx";
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресФайла);
ДвоичныеДанные.Записать(ПутьСохранения);
КонецПроцедуры
Если задача требует сохранения файла именно силами сервера (например, регламентным заданием по расписанию без участия клиентской части), разберем необходимые настройки сетевого окружения и сервера:
D:\1C_Export\, и в свойствах безопасности NTFS предоставьте учетной записи службы (usr1cv8) права «Изменение» и «Запись».Z:\), поскольку они монтируются в интерактивном сеансе конкретного пользователя и службе сервера не видны. Используйте только прямые UNC-пути: \\server\share\folder\. Для записи на сторонний сервер служба 1С должна запускаться под доменным пользователем, имеющим доступ к целевой сетевой папке.Обратите внимание на формирование имени файла: если в наименовании контрагента присутствуют кавычки (например, ООО "Электролюкс"), слеши или двоеточия, операционная система Windows вернет ошибку доступа или ошибку неверного синтаксиса имени файла. Перед записью обязательно удаляйте или заменяйте запрещенные знаки / \ : * ? " < > | с помощью функции СтрЗаменить().