Как правильно поместить файл во временное хранилище и прочитать его на сервере?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке на платформе 1С:Предприятие 8.3 начинающие разработчики часто сталкиваются с ошибкой "Ошибка доступа к файлу" при попытке прочитать файл на сервере. Рассмотрим классическую ситуацию: пользователь выбирает файл на своем компьютере через диалог, передает путь к этому файлу в серверную процедуру, но сервер не может его открыть. Разберем по шагам, почему это происходит и как правильно организовать передачу данных между клиентом и сервером.

Выясним причину ошибки: почему сервер не видит файл?

Проанализируем архитектуру 1С. Когда мы работаем в клиент-серверном варианте, код выполняется на двух разных физических (или логических) машинах:

  1. На клиенте: Здесь работает пользователь, и здесь доступен его жесткий диск (например, путь C:\Users\Documents\file.csv).
  2. На сервере: Здесь работает служба 1C:Enterprise Server. У этой службы нет и не может быть прямого доступа к локальным папкам пользователя.

Когда вы передаете строку с путем C:\Users\Documents\file.csv на сервер, метод Текст.Прочитать() пытается найти этот файл на диске самого сервера. Естественно, сервер выдает ошибку доступа, так как такого пути не существует или у учетной записи службы сервера (обычно это usr1cv8) нет прав на этот каталог.

Решение проблемы через временное хранилище

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

Способ 1: Использование классических методов (синхронно)

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


&НаКлиенте
Процедура ИмяФайлаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Диалог.Заголовок = "Выберите файл для загрузки";
    Диалог.МножественныйВыбор = Ложь;
    Диалог.Фильтр = "Текстовые файлы (*.csv)|*.csv";
    
    Если Диалог.Выбрать() Тогда
        ПутьКФайлу = Диалог.ПолноеИмяФайла;
        
        // Превращаем файл в ДвоичныеДанные прямо на клиенте
        ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);
        
        // Помещаем данные в хранилище и получаем уникальный адрес
        // Важно: вторым параметром передаем УникальныйИдентификатор формы!
        АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла, ЭтаФорма.УникальныйИдентификатор);
        
        // Теперь передаем на сервер только адрес (строку)
        ПрочитатьФайлНаСервере(АдресХранилища);
    КонецЕсли;
    
КонецПроцедуры

Рассмотрим, что мы сделали: метод ПоместитьВоВременноеХранилище загрузил содержимое файла в оперативную память сервера и вернул нам "ссылку" (строку вида e1cib/tempstorage/...). Теперь серверная процедура может легко получить эти данные по адресу.

Обработка данных на сервере

На стороне сервера нам нужно выполнить обратную операцию. Посмотрим на код серверной части:


&НаСервере
Процедура ПрочитатьФайлНаСервере(АдресХранилища)
    
    // Извлекаем двоичные данные из хранилища по адресу
    Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
    
    Если Данные <> Неопределено Тогда
        
        // Чтобы прочитать текст, можно сохранить данные во временный файл на сервере
        ИмяВременногоФайла = ПолучитьИмяВременногоФайла("csv");
        Данные.Записать(ИмяВременногоФайла);
        
        Текст = Новый ТекстовыйДокумент;
        Текст.Прочитать(ИмяВременногоФайла);
        
        // Далее обрабатываем строки файла...
        Для НомерСтроки = 1 По Текст.КоличествоСтрок() Цикл
            СтрокаФайла = Текст.ПолучитьСтроку(НомерСтроки);
            // Ваша логика обработки
        КонецЦикла;
        
        // Не забываем удалить временный файл после работы
        УдалитьФайлы(ИмяВременногоФайла);
        
    КонецЕсли;
    
КонецПроцедуры

Способ 2: Современный асинхронный подход (рекомендуется)

В современных версиях платформы 8.3.15+ использование синхронных вызовов (таких как Диалог.Выбрать) в веб-клиенте запрещено. Поэтому рассмотрим наиболее правильный вариант с использованием асинхронности. Проанализируем метод НачатьПомещениеФайлаНаСервер().


&НаКлиенте
Процедура ЗагрузитьФайлАсинхронно()
    
    // Описываем оповещение, которое сработает после выбора файла
    Оповещение = Новый ОписаниеОповещения("ЗавершитьЗагрузкуФайла", ЭтотОбъект);
    
    // Метод сразу открывает диалог и сам помещает файл в хранилище
    НачатьПомещениеФайлаНаСервер(Оповещение, , , , ЭтаФорма.УникальныйИдентификатор);
    
КонецПроцедуры

&НаКлиенте
Процедура ЗавершитьЗагрузкуФайла(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
    
    Если Результат Тогда
        // Файл уже в хранилище, адрес у нас в руках
        ОбработатьФайлНаСервере(Адрес);
    КонецЕсли;
    
КонецПроцедуры

Этот способ является предпочтительным, так как он работает во всех типах клиентов (тонкий, веб, мобильный) и не блокирует интерфейс пользователя во время загрузки больших файлов.

Оптимизация: чтение без записи на диск

Часто разработчики совершают лишнее действие — записывают полученные двоичные данные в файл на диске сервера через ПолучитьИмяВременногоФайла(). Проанализируем ситуацию: если файл небольшой, мы можем прочитать его прямо из памяти, используя Потоки. Это работает быстрее и не требует прав доступа к папкам сервера.


&НаСервере
Процедура ОбработатьФайлЧерезПоток(АдресХранилища)
    
    Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
    // Создаем поток из двоичных данных
    Поток = Данные.ОткрытьПотокДляЧтения();
    
    ЧтениеТекста = Новый ЧтениеТекста(Поток, КодировкаТекста.UTF8);
    СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();
    
    Пока СтрокаФайла <> Неопределено Цикл
        // Обработка строки
        СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();
    КонецЦикла;
    
    ЧтениеТекста.Закрыть();
    Поток.Закрыть();
    
КонецПроцедуры

Важные нюансы работы с временным хранилищем

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

Подводя итог, можно сказать: никогда не передавайте на сервер путь к локальному файлу. Всегда используйте схему: Клиент (Двоичные данные) -> Временное хранилище (Адрес) -> Сервер (Получение по адресу). Это единственный корректный путь разработки в современной экосистеме 1С.

← На главную