При разработке на платформе 1С:Предприятие 8.3 начинающие разработчики часто сталкиваются с ошибкой "Ошибка доступа к файлу" при попытке прочитать файл на сервере. Рассмотрим классическую ситуацию: пользователь выбирает файл на своем компьютере через диалог, передает путь к этому файлу в серверную процедуру, но сервер не может его открыть. Разберем по шагам, почему это происходит и как правильно организовать передачу данных между клиентом и сервером.
Проанализируем архитектуру 1С. Когда мы работаем в клиент-серверном варианте, код выполняется на двух разных физических (или логических) машинах:
C:\Users\Documents\file.csv).1C:Enterprise Server. У этой службы нет и не может быть прямого доступа к локальным папкам пользователя.Когда вы передаете строку с путем C:\Users\Documents\file.csv на сервер, метод Текст.Прочитать() пытается найти этот файл на диске самого сервера. Естественно, сервер выдает ошибку доступа, так как такого пути не существует или у учетной записи службы сервера (обычно это usr1cv8) нет прав на этот каталог.
Единственный надежный способ передать файл с компьютера пользователя на сервер — это использовать Временное хранилище. Рассмотрим этот процесс как последовательность действий: превращаем файл в поток байтов (двоичные данные), отправляем этот поток в специальную область памяти на сервере, получаем адрес этой области и уже на сервере извлекаем данные. Проанализируем, как это реализовать программно.
Этот способ подходит для старых конфигураций или работы в толстом клиенте, однако важно понимать его логику. Разберем пример кода:
&НаКлиенте
Процедура ИмяФайлаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Заголовок = "Выберите файл для загрузки";
Диалог.МножественныйВыбор = Ложь;
Диалог.Фильтр = "Текстовые файлы (*.csv)|*.csv";
Если Диалог.Выбрать() Тогда
ПутьКФайлу = Диалог.ПолноеИмяФайла;
// Превращаем файл в ДвоичныеДанные прямо на клиенте
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);
// Помещаем данные в хранилище и получаем уникальный адрес
// Важно: вторым параметром передаем УникальныйИдентификатор формы!
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла, ЭтаФорма.УникальныйИдентификатор);
// Теперь передаем на сервер только адрес (строку)
ПрочитатьФайлНаСервере(АдресХранилища);
КонецЕсли;
КонецПроцедуры
Рассмотрим, что мы сделали: метод ПоместитьВоВременноеХранилище загрузил содержимое файла в оперативную память сервера и вернул нам "ссылку" (строку вида e1cib/tempstorage/...). Теперь серверная процедура может легко получить эти данные по адресу.
На стороне сервера нам нужно выполнить обратную операцию. Посмотрим на код серверной части:
&НаСервере
Процедура ПрочитатьФайлНаСервере(АдресХранилища)
// Извлекаем двоичные данные из хранилища по адресу
Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
Если Данные <> Неопределено Тогда
// Чтобы прочитать текст, можно сохранить данные во временный файл на сервере
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("csv");
Данные.Записать(ИмяВременногоФайла);
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(ИмяВременногоФайла);
// Далее обрабатываем строки файла...
Для НомерСтроки = 1 По Текст.КоличествоСтрок() Цикл
СтрокаФайла = Текст.ПолучитьСтроку(НомерСтроки);
// Ваша логика обработки
КонецЦикла;
// Не забываем удалить временный файл после работы
УдалитьФайлы(ИмяВременногоФайла);
КонецЕсли;
КонецПроцедуры
В современных версиях платформы 8.3.15+ использование синхронных вызовов (таких как Диалог.Выбрать) в веб-клиенте запрещено. Поэтому рассмотрим наиболее правильный вариант с использованием асинхронности. Проанализируем метод НачатьПомещениеФайлаНаСервер().
&НаКлиенте
Процедура ЗагрузитьФайлАсинхронно()
// Описываем оповещение, которое сработает после выбора файла
Оповещение = Новый ОписаниеОповещения("ЗавершитьЗагрузкуФайла", ЭтотОбъект);
// Метод сразу открывает диалог и сам помещает файл в хранилище
НачатьПомещениеФайлаНаСервер(Оповещение, , , , ЭтаФорма.УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ЗавершитьЗагрузкуФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
Если Результат Тогда
// Файл уже в хранилище, адрес у нас в руках
ОбработатьФайлНаСервере(Адрес);
КонецЕсли;
КонецПроцедуры
Этот способ является предпочтительным, так как он работает во всех типах клиентов (тонкий, веб, мобильный) и не блокирует интерфейс пользователя во время загрузки больших файлов.
Часто разработчики совершают лишнее действие — записывают полученные двоичные данные в файл на диске сервера через ПолучитьИмяВременногоФайла(). Проанализируем ситуацию: если файл небольшой, мы можем прочитать его прямо из памяти, используя Потоки. Это работает быстрее и не требует прав доступа к папкам сервера.
&НаСервере
Процедура ОбработатьФайлЧерезПоток(АдресХранилища)
Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
// Создаем поток из двоичных данных
Поток = Данные.ОткрытьПотокДляЧтения();
ЧтениеТекста = Новый ЧтениеТекста(Поток, КодировкаТекста.UTF8);
СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();
Пока СтрокаФайла <> Неопределено Цикл
// Обработка строки
СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();
КонецЦикла;
ЧтениеТекста.Закрыть();
Поток.Закрыть();
КонецПроцедуры
Для стабильной работы механизмов загрузки файлов необходимо придерживаться следующих правил:
ЭтаФорма.УникальныйИдентификатор вторым параметром при помещении в хранилище. Это гарантирует, что данные будут "жить" столько же, сколько открыта форма, и автоматически очистятся после её закрытия. Если этого не сделать, данные могут исчезнуть при первом же серверном вызове.КодировкаТекста.UTF8 или "windows-1251"). Автоматическое определение часто ошибается, что приводит к появлению нечитаемых символов.Записать()), убедитесь, что у пользователя usr1cv8 есть права на запись в папку Temp операционной системы сервера.Подводя итог, можно сказать: никогда не передавайте на сервер путь к локальному файлу. Всегда используйте схему: Клиент (Двоичные данные) -> Временное хранилище (Адрес) -> Сервер (Получение по адресу). Это единственный корректный путь разработки в современной экосистеме 1С.