Перенос файлов с клиентского рабочего места на сервер — это классическая задача в 1С, с которой сталкивается практически каждый разработчик при реализации функционала прикрепления сканов, импорта данных или хранения архивов. На первый взгляд задача кажется простой, но в среде управляемого приложения она требует четкого понимания разделения контекстов исполнения кода. В этой статье мы подробно разберем, почему возникает ошибка «Каталог не обнаружен», и научимся правильно передавать данные между клиентом и сервером.
Проанализируем ситуацию, описанную в сообщениях форума. Разработчик пытается выполнить следующий код в серверной процедуре:
&НаСервере
Процедура СохранитьФайлНаСервере()
// Объект.Файл содержит путь "C:\Users\Documents\report.pdf"
ДвоичныеДанные = Новый ДвоичныеДанные(Объект.Файл);
// Здесь возникает ошибка: Каталог не обнаружен
КонецПроцедуры
Выясним причину этой ошибки. Когда код выполняется с директивой &НаСервере, он исполняется на компьютере, где установлена служба 1C:Enterprise Server. Когда вы передаете туда строку с путем C:\Users\..., сервер пытается найти этот файл на своем собственном жестком диске. Естественно, сервер «не видит» файлы на диске «C:» вашего локального компьютера. Для сервера локальный диск пользователя — это чужая, недоступная территория.
Чтобы файл попал на сервер, его нужно сначала прочитать в оперативную память на клиенте, передать в специальную буферную зону (временное хранилище) и только потом «забрать» на стороне сервера.
Рассмотрим по шагам самый надежный и проверенный способ реализации этой задачи. Нам понадобятся две процедуры: одна на клиенте для захвата файла, вторая на сервере для его сохранения на диск.
Шаг 1: Работа на клиенте. Мы должны превратить файл в объект типа ДвоичныеДанные и поместить его во временное хранилище. Метод ПоместитьВоВременноеХранилище возвращает уникальный адрес (строку), по которому сервер сможет найти эти данные.
&НаКлиенте
Процедура ПеренестиФайлНаСервер()
// Проверяем, указан ли путь к файлу
Если ПустаяСтрока(Объект.Файл) Тогда
Возврат;
КонецЕсли;
// Читаем файл в двоичные данные именно НА КЛИЕНТЕ
ДвоичныеДанные = Новый ДвоичныеДанные(Объект.Файл);
// Помещаем во временное хранилище.
// ЭтаФорма.УникальныйИдентификатор нужен для привязки жизни хранилища к форме.
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ЭтаФорма.УникальныйИдентификатор);
// Теперь передаем адрес на сервер
ЗаписатьФайлНаСервере(АдресХранилища, "ИмяФайла.pdf");
КонецПроцедуры
Шаг 2: Работа на сервере. Теперь, когда данные находятся в «облаке» сервера, мы можем их извлечь и записать в нужную нам папку.
&НаСервере
Процедура ЗаписатьФайлНаСервере(АдресХранилища, ИмяФайла)
// Получаем данные из хранилища по адресу
ДанныеДляЗаписи = ПолучитьИзВременногоХранилища(АдресХранилища);
Если ДанныеДляЗаписи <> Неопределено Тогда
// Формируем полный путь на сервере
// ВАЖНО: Путь должен быть доступен для пользователя, под которым запущен сервер 1С
ПутьНаСервере = "D:\FileStorage\" + ИмяФайла;
Попытка
ДанныеДляЗаписи.Записать(ПутьНаСервере);
Сообщить("Файл успешно сохранен на сервере!");
Исключение
Сообщить("Ошибка записи: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Начиная с версии платформы 8.3.15, компания 1С рекомендует отказываться от синхронных методов работы с файлами. Метод Новый ДвоичныеДанные(Путь) блокирует интерфейс, если файл большой. Разберем, как сделать это правильно через НачатьПомещениеФайлаНаСервер. Это особенно актуально для веб-клиента, где прямой доступ к файлам ограничен.
&НаКлиенте
Процедура НачатьЗагрузкуФайла()
// Описание оповещения, которое сработает после того, как файл попадет в хранилище
Оповещение = Новый ОписаниеОповещения("ПослеПомещенияФайла", ЭтотОбъект);
// Параметры помещения файла
ПараметрыФайла = Новый ПараметрыПомещенияФайла;
// Запускаем асинхронный процесс
НачатьПомещениеФайлаНаСервер(Оповещение, , , , ПараметрыФайла, ЭтаФорма.УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ПослеПомещенияФайла(Результат, ДополнительныеПараметры) Экспорт
Если Результат <> Неопределено Тогда
// Результат.Адрес - это уже готовый адрес во временном хранилище
ЗаписатьНаДискСервера(Результат.Адрес, Результат.СсылкаНаФайл.Имя);
КонецЕсли;
КонецПроцедуры
Этот метод хорош тем, что он автоматически открывает диалог выбора файла, если путь не указан, и работает максимально корректно в браузере.
Проанализируем сопутствующие проблемы, которые могут возникнуть, даже если ваш код логически верен.
USR1CV8). Убедитесь, что у этого системного пользователя есть права «Запись» и «Изменение» на папку D:\FileStorage\ (или ту, которую вы используете).C:\Folder\), код работать не будет. Рекомендуем использовать функцию ПолучитьРазделительПути() или проверять операционную систему через СистемнаяИнформация.Записать(), обязательно проверьте, существует ли целевая папка на сервере. Если нет — создайте её.Посмотрим на пример правильной подготовки каталога на сервере:
&НаСервере
Процедура ПроверитьИСоздатьКаталог(ПолныйПуть)
ОбъектФайл = Новый Файл(ПолныйПуть);
Каталог = ОбъектФайл.Путь; // Получаем только путь без имени файла
Если НЕ ОбщегоНазначенияКлиентСервер.КаталогСуществует(Каталог) Тогда
СоздатьКаталог(Каталог);
КонецЕсли;
КонецПроцедуры
Для успешного копирования файла на сервер нужно запомнить главное правило: серверная процедура не может напрямую обращаться к файловой системе клиента. Все взаимодействие происходит через «посредника» — временное хранилище. Процесс всегда выглядит так: Чтение на клиенте -> Помещение в хранилище -> Вызов сервера -> Получение из хранилища -> Запись на диск сервера. Соблюдая эту структуру и не забывая про права доступа службы USR1CV8, вы сможете реализовать надежный механизм работы с файлами в любой конфигурации 1С.