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

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

1С: как сохранить файл на сервере

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

Задача сохранить файл на сервере 1С возникает постоянно: выгрузка отчёта, обмен с внешней системой, загрузка прайса от пользователя, формирование XML для ЭДО. При этом в клиент-серверном режиме код выполняется на сервере, а файл пользователя находится на клиенте — поэтому простая конструкция «записать файл» из файловой базы на сервере не сработает. Нужно понимать, где именно выполняется код и куда реально пишутся данные.

Основная сложность — разделение контекстов. Код с директивой &НаСервере имеет доступ только к файловой системе сервера 1С, а диалог выбора файла доступен только на клиенте. Поэтому типовая схема выглядит так: клиент помещает файл во временное хранилище, сервер забирает его оттуда и сохраняет в нужный каталог. Либо наоборот — сервер формирует файл и отдаёт его клиенту.

Ниже разобраны оба направления: помещение файла с клиента на сервер, сохранение сформированного на сервере файла в каталог, выбор каталога, права доступа и типичные ошибки, из-за которых «файл не сохраняется».

Как устроена работа с файлами в клиент-серверном режиме

В файловой базе клиент и «сервер» — фактически одна машина, поэтому путь C:\Отчёты\файл.xlsx доступен из любого контекста. В клиент-серверном режиме код &НаСервере исполняется процессом rphost на сервере приложений, и он видит только диски этого сервера. Путь C:\... в серверном коде укажет на диск C сервера, а не компьютера пользователя.

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

Сохранение файла, выбранного пользователем, на сервере

Типовой сценарий: пользователь нажимает «Загрузить файл», выбирает файл у себя, а он сохраняется в каталог на сервере. Реализуется это асинхронным методом НачатьПомещениеФайлаНаСервер (в старых конфигурациях — связка ПоместитьФайл + НачатьПомещениеФайла).

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

Пример кода. Клиентская часть:

&НаКлиенте

Процедура ЗагрузитьФайл(Команда)

ОписаниеОповещения = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);

НачатьПомещениеФайлаНаСервер(ОписаниеОповещения, , , , , УникальныйИдентификатор);

КонецПроцедуры

&НаКлиенте

Процедура ПослеПомещенияФайла(ОписаниеПомещенногоФайла, ДопПараметры) Экспорт

Если ОписаниеПомещенногоФайла = Неопределено Тогда

Возврат; // пользователь отменил выбор

КонецЕсли;

СохранитьНаСервере(ОписаниеПомещенногоФайла.Адрес,

ОписаниеПомещенногоФайла.СсылкаНаФайл.Имя);

КонецПроцедуры

Серверная часть:

&НаСервере

Процедура СохранитьНаСервере(Адрес, ИмяФайла)

Каталог = "D:\1C_Files\Загрузки\";

Если Не СтрЗаканчиваетсяНа(Каталог, "\") Тогда

Каталог = Каталог + "\";

КонецЕсли;

ДвоичныеДанные = ПолучитьИзВременногоХранилища(Адрес);

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

УдалитьИзВременногоХранилища(Адрес);

КонецПроцедуры

Сохранение файла, сформированного на сервере

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

&НаСервере

Процедура ВыгрузитьОтчетНаСервере()

Текст = Новый ЗаписьТекста("D:\1C_Files\export\data.csv", КодировкаТекста.UTF8);

Текст.ЗаписатьСтроку("Номенклатура;Остаток");

// ... запись данных ...

Текст.Закрыть();

КонецПроцедуры

Для табличных документов используется метод Записать с указанием типа файла: ТабДок.Записать(Путь, ТипФайлаТабличногоДокумента.XLSX). Для XML — объекты ЗаписьXML, для произвольных бинарных данных — ДвоичныеДанные.Записать() или потоки (ФайловыйПоток), которые удобнее при больших объёмах.

Как отдать файл пользователю после формирования

Если цель — не просто сохранить файл на сервере, а отдать его пользователю, серверный код помещает данные во временное хранилище (ПоместитьВоВременноеХранилище), а клиент вызывает НачатьПолучениеФайлаССервера или ПолучитьФайл с диалогом сохранения. Это стандартная схема кнопки «Скачать» в типовых конфигурациях.

Куда сохранять: выбор каталога и права доступа

Каталог для сохранения должен существовать и быть доступен учётной записи, под которой работает служба «Агент сервера 1С:Предприятия». По умолчанию это часто системная учётная запись (например, USR1CV8), у которой нет прав на произвольные папки и сетевые ресурсы. Это причина номер один ошибок «файл не записывается».

Практические рекомендации по каталогу:

  • создайте выделенный каталог на сервере, например D:\1C_Files, и явно выдайте учётной записи агента сервера права на запись;
  • для сетевых путей (\\server\share) убедитесь, что доступ есть именно у учётной записи службы, а не у пользователя Windows — проверка «у меня открывается» ничего не доказывает;
  • не сохраняйте рабочие файлы в каталог базы или установки платформы;
  • путь к каталогу лучше хранить в константе или параметре обмена, а не зашивать в код — при переносе базы путь изменится.

Безопасная работа с именем файла

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

Альтернативы: хранение файлов в базе и томах

Сохранение в каталог сервера — не единственный и не всегда лучший вариант. В типовых конфигурациях на БСП файлы обычно хранятся в информационной базе (в виде двоичных данных в хранилище значения) или в томах на диске через подсистему «Работа с файлами». Это даёт версии, права доступа на уровне 1С и корректное резервное копирование вместе с базой.

Сравнение вариантов

Каталог на сервере

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

Хранение в базе (хранилище значения)

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

Тома хранения файлов (БСП)

Файлы на диске, но под управлением 1С: версии, права, перенос между томами. Требует использования БСП или аналогичной подсистемы.

Типичные ошибки и их признаки

Типичные ошибки
01
Использование ПоместитьФайл синхронно в тонком/веб-клиенте — метод недоступен или требует модальных вызовов; применяйте асинхронный НачатьПомещениеФайлаНаСервер
02
Сохранение по пути C:\ из серверного кода — файл пишется на диск сервера, а пользователь ищет его у себя
03
Отсутствие прав у учётной записи агента сервера — ошибка «Отказано в доступе» при записи
04
Несуществующий каталог — Записать() не создаёт промежуточные каталоги автоматически, нужен СоздатьКаталог
05
Конфликт имён при одновременной работе пользователей — файл перезаписывается чужой загрузкой
06
Забытое УдалитьИзВременногоХранилища — рост потребления памяти сервера при массовых операциях

Отдельная группа проблем — кодировки. Текстовый файл, записанный без указания кодировки, может открываться «крякозябрами» в принимающей системе. Всегда явно задавайте кодировку в ЗаписьТекста (чаще всего UTF-8) и согласуйте её с той стороной, которая будет файл читать.

Проверка результата

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

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

Файл появился в каталоге сервера
Норма

Файл существует, размер больше нуля и совпадает с ожидаемым

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

Файла нет или размер 0 байт — проверяйте права и путь

Содержимое файла
Норма

Файл открывается целевой программой, данные читаются корректно

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

Ошибка открытия или «крякозябры» — неверный формат записи или кодировка

Повторная загрузка
Норма

Второй файл сохраняется рядом, не затирая первый

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

Перезапись — нет уникализации имён

Работа под другим пользователем
Норма

Сохранение работает у всех пользователей

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

Работает только у администратора — проблема прав на каталог

Для отладки полезно временно добавить запись полного пути сохранённого файла в журнал регистрации (ЗаписьЖурналаРегистрации) — тогда по журналу видно, куда именно сервер пытался писать, и легко отличить проблему прав от проблемы пути.

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

Можно ли сохранить файл на сервере без временного хранилища?

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

Почему возникает ошибка «Отказано в доступе» при записи файла?

Чаще всего у учётной записи, под которой работает служба агента сервера 1С, нет прав на запись в целевой каталог. Проверьте, под какой учётной записью запущена служба, и выдайте ей права на каталог. Для сетевых путей проверяйте и разрешения общей папки, и NTFS-права.

Как сохранить файл в сетевую папку с сервера 1С?

Укажите UNC-путь вида \\server\share\file.txt и убедитесь, что учётная запись агента сервера имеет туда доступ. Подключённые сетевые диски (Z:\) из серверного кода лучше не использовать — они существуют в контексте конкретного пользователя и службе недоступны.

Чем отличается НачатьПомещениеФайлаНаСервер от ПоместитьФайл?

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

Как сохранить табличный документ в Excel на сервере?

Вызовите метод Записать у табличного документа с типом файла: ТабДок.Записать("D:\1C_Files\отчет.xlsx", ТипФайлаТабличногоДокумента.XLSX). Каталог должен существовать, а учётная запись сервера — иметь права на запись.

Безопасно ли сохранять файлы с именами, которые передал пользователь?

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

Итог

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

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