Разработка и Конфигурация · 12 мин
Как передать файл на сервер в 1С: способы и примеры
Как передать файл с клиента на сервер 1С: временное хранилище, НачатьПомещениеФайла, асинхронные методы, передача между сеансами. Примеры кода и типичные ошибки.
Передача файла на сервер — одна из базовых задач при доработке конфигураций 1С: загрузка прайсов, импорт выписок, прикрепление сканов документов, обмен с внешними системами. Проблема в том, что в клиент-серверном режиме код на клиенте и код на сервере выполняются на разных машинах, и просто прочитать файл с диска пользователя в серверной процедуре нельзя.
Платформа 1С:Предприятие 8.3 предлагает несколько штатных механизмов: помещение файла во временное хранилище, передачу через параметры серверных вызовов в виде двоичных данных, а также файловые потоки и асинхронные методы. Выбор зависит от размера файла, режима работы (тонкий клиент, веб-клиент, файловая база) и того, нужно ли хранить файл постоянно.
Ниже разобраны рабочие подходы с примерами кода, ограничения каждого способа и типичные ошибки, из-за которых передача «не работает» или приводит к утечкам памяти на сервере.
Почему нельзя просто прочитать файл на сервере
В клиент-серверном режиме сервер 1С и клиентское приложение физически работают на разных компьютерах. Код, выполняемый в серверной процедуре (директива &НаСервере), не имеет доступа к диску пользователя. Путь вида C:\Документы\прайс.xlsx на сервере либо не существует, либо указывает на совершенно другую машину.
Даже в файловом режиме, где клиент и «сервер» формально на одном компьютере, полагаться на локальные пути нельзя: код должен быть переносимым, и при переходе базы в клиент-серверный режим такая логика сломается. Поэтому платформа требует явной передачи содержимого файла между клиентом и сервером.
Единственное исключение — файлы, размещённые на общем сетевом ресурсе, доступном и клиенту, и серверу под одинаковым путём (например, UNC-путь \\fileserver\share). Такой подход используется, но требует настройки прав доступа учётной записи, под которой работает агент сервера 1С.
Передача файла через временное хранилище
Временное хранилище — основной механизм платформы для передачи данных между клиентом и сервером. Клиент помещает файл в хранилище и получает адрес (строку вида e1cib/tempstorage/...), который передаётся в серверную процедуру. Сервер извлекает по этому адресу объект типа ДвоичныеДанные и дальше работает с ним: записывает на диск, передаёт в обработку, сохраняет в информационную базу.
В современных версиях платформы рекомендуется использовать асинхронные методы, поскольку синхронный ПоместитьФайл в веб-клиенте и при включённом режиме модальности может быть недоступен. Асинхронный вариант выглядит так:
&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
НачатьПомещениеФайлаНаСервер(ОписаниеОповещения, , , , ,
"C:\Документы\прайс.xlsx", УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПомещенияФайла(ОписаниеФайла, ДопПараметры) Экспорт
Если ОписаниеФайла.ПомещениеФайлаОтменено Тогда
Возврат;
КонецЕсли;
ОбработатьФайлНаСервере(ОписаниеФайла.Адрес);
КонецПроцедуры
&НаСервере
Процедура ОбработатьФайлНаСервере(АдресХранилища)
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанные.Записать(ИмяВременногоФайла);
// дальнейшая обработка файла
УдалитьИзВременногоХранилища(АдресХранилища);
КонецПроцедуры
Обратите внимание на передачу УникальныйИдентификатор формы — он привязывает данные хранилища к времени жизни формы. Без этого адрес может стать недействительным после закрытия формы или, наоборот, данные останутся висеть в памяти сервера до конца сеанса.
Выбор файла пользователем через диалог
На практике путь к файлу редко известен заранее — пользователь выбирает его через диалог. Для этого используется ДиалогВыбораФайла в связке с помещением в хранилище, либо более удобный метод НачатьПомещениеФайлаНаСервер без указания имени файла — тогда платформа сама покажет диалог выбора.
&НаКлиенте
Процедура ВыбратьИЗагрузить(Команда)
Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
// Интерактивно = Истина — платформа покажет диалог выбора файла
НачатьПомещениеФайлаНаСервер(Оповещение, , , , Истина, ,
УникальныйИдентификатор);
КонецПроцедуры
Если нужен свой диалог с фильтром по расширениям, используйте ДиалогВыбораФайла с режимом Открытие и метод Показать с описанием оповещения. В веб-клиенте синхронный вызов Выбрать() не работает — только асинхронный вариант.
- 1На клиенте вызовите НачатьПомещениеФайлаНаСервер с описанием оповещения
- 2В обработчике оповещения проверьте, что помещение не отменено пользователем
- 3Передайте полученный адрес хранилища в серверную процедуру
- 4На сервере получите двоичные данные через ПолучитьИзВременногоХранилища
- 5Обработайте данные и при необходимости сохраните их в базу
- 6Удалите данные из хранилища вызовом УдалитьИзВременногоХранилища
Передача небольших данных напрямую параметром
Если данные небольшие (например, XML- или JSON-строка, сгенерированная на клиенте), файл можно вообще не создавать: передайте строку или объект ДвоичныеДанные напрямую параметром серверной процедуры. Платформа сериализует значение и передаст его по каналу связи.
Для двоичных данных, прочитанных на клиенте, схема такая: прочитать файл в ДвоичныеДанные (асинхронно, через НачатьПомещениеФайлаВоВременноеХранилище или файловые потоки), затем передать объект параметром. Однако для больших файлов этот путь хуже хранилища: данные будут сериализованы целиком при вызове, что менее эффективно и может вызвать ошибки при ограничениях на размер передаваемых данных.
Сравнение способов передачи
Универсальный способ для файлов любого размера; требует очистки хранилища и привязки к форме
Подходит для небольших строк и двоичных данных; не рекомендуется для больших файлов
Клиент кладёт файл в шару, сервер читает по UNC-пути; требует настройки прав учётной записи агента сервера
Когда файл нужно передать не на сервер 1С, а во внешнюю систему; используется HTTPСоединение или HTTPЗапрос
Запись файла на диск сервера
Частая задача — не просто получить файл на сервере, а сохранить его в каталог на серверной машине (например, для последующей обработки регламентным заданием). После получения двоичных данных из хранилища используйте метод Записать:
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилища);
ДвоичныеДанные.Записать("\\server\exchange\import\прайс.xlsx");
Критический момент — права доступа. Запись выполняется под учётной записью, от имени которой работает служба агента сервера 1С (по умолчанию это может быть локальная системная учётная запись, у которой нет доступа к сетевым ресурсам). Если запись в сетевой каталог завершается ошибкой доступа, назначьте службе агента доменную учётную запись с правами на нужный каталог.
Ограничения веб-клиента и тонкого клиента
В веб-клиенте действуют дополнительные ограничения браузера: синхронные модальные вызовы запрещены, прямой доступ к файловой системе возможен только через диалог выбора, а для работы с файлами может потребоваться расширение работы с файлами. Если код пишется с расчётом на веб-клиент, используйте только асинхронные методы из семейства Начать....
В тонком клиенте ограничений меньше, но включённый в конфигураторе режим использования модальности может запретить синхронные вызовы — тогда ПоместитьФайл и ДиалогВыбораФайла.Выбрать() вызовут исключение. Проверить поведение можно, запустив базу в том же режиме, в котором работают пользователи.
Проверка результата и отладка
После передачи убедитесь, что на сервер пришли именно те данные. Простейшие проверки: размер двоичных данных (ДвоичныеДанные.Размер()) должен совпадать с размером исходного файла; если файл текстовый — прочитайте первые строки и сверьте содержимое. Для Excel и других форматов достаточно успешного открытия файла соответствующим механизмом (например, через ТабличныйДокумент.Прочитать).
Если ПолучитьИзВременногоХранилища возвращает Неопределено, чаще всего причина в том, что адрес использован повторно после удаления, передан в другой сеанс или форма, к которой привязано хранилище, уже закрыта. Отлаживайте такие места, выводя адрес и размер данных в журнал регистрации или сообщения.
Как проверить результат
Совпадает с размером исходного файла
Ноль или значительно меньше исходного
Возвращает объект ДвоичныеДанные
Возвращает Неопределено — адрес недействителен или данные удалены
Открывается штатным приложением без ошибок
Файл не создаётся (ошибка прав доступа) или повреждён
После обработки данные хранилища удаляются
Растёт потребление памяти рабочими процессами
Частые вопросы
Можно ли передать файл на сервер без временного хранилища?
Да, для небольших данных: передайте строку или объект ДвоичныеДанные параметром серверной процедуры. Либо используйте общий сетевой каталог, доступный и клиенту, и серверу. Но для файлов заметного размера временное хранилище остаётся штатным и самым надёжным вариантом.
Почему ПолучитьИзВременногоХранилища возвращает Неопределено?
Основные причины: адрес используется после вызова УдалитьИзВременногоХранилища, адрес передан в другой сеанс (хранилище привязано к сеансу), либо форма, чей уникальный идентификатор был указан при помещении, уже закрыта. Проверьте, что адрес используется в том же сеансе и до удаления данных.
Как передать файл в фоновое задание?
Напрямую адрес временного хранилища в фоновое задание передавать нельзя — оно выполняется в другом сеансе. Сначала в текущем сеансе получите двоичные данные из хранилища и сохраните их, например, во временный файл на сервере или в ХранилищеЗначения в базе, а в фоновое задание передайте путь к файлу или ссылку на объект.
Работает ли передача файлов в веб-клиенте?
Да, но только через асинхронные методы (НачатьПомещениеФайлаНаСервер и аналоги) и с учётом ограничений браузера: доступ к файловой системе возможен только через диалог выбора файла, для части операций требуется расширение работы с файлами. Синхронные ПоместитьФайл и диалоги с методом Выбрать() в веб-клиенте не работают.
Как передать файл с сервера обратно клиенту?
Зеркальная схема: на сервере поместите двоичные данные во временное хранилище (ПоместитьВоВременноеХранилище) и верните адрес клиенту, а на клиенте вызовите НачатьПолучениеФайлаССервера или ПолучитьФайл, указав адрес и путь сохранения. После скачивания удалите данные из хранилища.
Есть ли ограничение на размер передаваемого файла?
Жёсткого ограничения платформы на размер файла в хранилище нет, но на практике большие файлы увеличивают потребление памяти сервера и время передачи. Для очень больших объёмов разумнее использовать обмен через общий каталог или специализированные механизмы (например, передачу частями), а не загружать файл целиком в память.
Что важно запомнить
Файл с клиента на сервер 1С передаётся через временное хранилище: НачатьПомещениеФайлаНаСервер на клиенте, ПолучитьИзВременногоХранилища на сервере. Используйте асинхронные методы, привязывайте хранилище к форме, удаляйте данные после обработки и не доверяйте именам файлов от клиента при записи на диск сервера.