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

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

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

Анализ исходной задачи

Рассмотрим ситуацию, описанную автором. Задача состоит в том, чтобы сформировать CSV-файл с данными (Номенклатура, Количество, Сумма) и сохранить его не на компьютере пользователя, а непосредственно на жестком диске сервера, где работает служба 1С.

Исходный код автора использует объект ТекстовыйДокумент (для более сложных трансформаций можно использовать модуль «Трансформер»). Давайте проанализируем логику:


&НаСервере
Процедура СерверНаСервере()
    Документ = Новый ТекстовыйДокумент;
    
    // Формируем заголовок
    СтрНом = "Номенклатура;" + "КоличествоОстаток;" + "СуммаОстаток";
    Документ.ДобавитьСтроку(СтрНом);
    
    // Обходим выборку данных
    Для каждого Строка из Объект.Результат Цикл
        СтрНом = ПереводВСтроку(Строка.номенклатура) + ";" + 
                 ПереводВСтроку(Строка.КоличествоОстаток) + ";" + 
                 ПереводВСтроку(Строка.СуммаОстаток);
        Документ.ДобавитьСтроку(СтрНом);
    КонецЦикла;
    
    // Здесь требуется код сохранения
КонецПроцедуры

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

Решение 1: Использование объекта ТекстовыйДокумент

Самый простой ответ, который и был подсказан в обсуждении, заключается в использовании метода Записать. Важно понимать, что когда код выполняется внутри директивы &НаСервере, он "видит" файловую систему именно того компьютера, на котором запущен сервер 1С.

Следовательно, чтобы сохранить файл, достаточно указать локальный путь на сервере.


// Полный путь к файлу на диске СЕРВЕРА
ПутьКФайлу = "D:\Exchange\Report.csv"; 

// Сохранение
Документ.Записать(ПутьКФайлу);

Казалось бы, всё просто. Однако, при реализации этого подхода мы неизбежно столкнемся с рядом подводных камней, которые необходимо разобрать подробнее.

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

Давайте углубимся в технические детали, которые часто упускаются из виду, но являются критичными для стабильной работы механизма.

1. Права доступа (Permissions)

Это самая частая причина ошибок типа "Ошибка доступа к файлу" или "Каталог не найден". Серверный код 1С выполняется не от имени вашего доменного пользователя, а от имени служебной учетной записи, под которой запущена служба агента сервера 1С (чаще всего это USR1CV8 или системная запись Local System).

Мы должны убедиться, что:

  1. Папка, в которую мы пишем (в примере D:\Exchange\), физически существует на сервере (аналогично тому, как происходит выгрузка внешних отчетов и обработок в каталог).
  2. У пользователя USR1CV8 есть полные права (чтение и запись) на эту папку в свойствах безопасности Windows (или Linux).

Важно: Сетевые диски, подключенные у вас в "Мой компьютер" (например, диск Z:), серверу обычно недоступны. Если нужно сохранить файл в сетевую папку, следует использовать UNC-пути, например: \\FileServer\Share\Report.csv, и убедиться, что у служебного пользователя сервера 1С есть доступ к этому сетевому ресурсу.

2. Кодировка файла для Excel

В исходном примере метод Записать используется без параметров кодировки. По умолчанию 1С часто сохраняет файлы в UTF-8. Если открыть такой CSV-файл в Excel (особенно старых версий) в Windows, вместо русских букв мы увидим некорректные символы ("кракозябры").

Чтобы файл корректно открывался в Excel, рекомендуется явно указывать кодировку ANSI (Windows-1251) или использовать конвертор из CSV в XLS.


// Сохраняем в кодировке Windows (ANSI)
Документ.Записать(ПутьКФайлу, КодировкаТекста.ANSI);

3. Кроссплатформенность (Linux vs Windows)

Современные сервера 1С часто работают на Linux. В Linux нет дисков C: или D:, а разделителем пути служит прямой слеш /, а не обратный \. Чтобы ваш код был универсальным, лучше не прописывать разделители вручную, а использовать встроенную функцию платформы ПолучитьРазделительПути().

Решение 2: Профессиональный подход (ЗаписьТекста)

В обсуждении справедливо заметили: "Зачем создан ТекстовыйДокумент?". Давайте разберем этот момент. Объект ТекстовыйДокумент хранит всё содержимое файла в оперативной памяти. Если вам нужно выгрузить отчет на 500 000 строк, этот объект "съест" сотни мегабайт оперативной памяти сервера, что может привести к замедлению работы всей системы.

Более правильным и производительным способом для записи файлов является использование объекта ЗаписьТекста. Он пишет данные в файл потоком, строка за строкой, практически не расходуя оперативную память.

Давайте перепишем код автора, используя этот оптимальный подход:


&НаСервере
Процедура СохранитьФайлНаСервереОптимально()
    
    // Формируем путь. Лучше вынести путь в константу или настройку
    ПутьКФайлу = "D:\Exchange\Report.csv";
    
    // Создаем объект записи.
    // Указываем кодировку ANSI для корректного открытия в Excel под Windows
    Запись = Новый ЗаписьТекста(ПутьКФайлу, КодировкаТекста.ANSI);
    
    // Формируем и записываем заголовок
    Заголовок = "Номенклатура;Количество;Сумма" + Символы.ПС;
    Запись.Записать(Заголовок);
    
    // Обходим выборку данных
    Для каждого СтрокаДанных Из Объект.Результат Цикл
        
        // Формируем строку CSV.
        // Важно: экранирование спецсимволов (если в названии есть точка с запятой)
        // Для простоты примера используем упрощенную склейку
        СтрФайла = Строка(СтрокаДанных.Номенклатура) + ";" + 
                   XMLСтрока(СтрокаДанных.КоличествоОстаток) + ";" + 
                   XMLСтрока(СтрокаДанных.СуммаОстаток) + Символы.ПС;
                   
        // Записываем строку сразу в файл на диск
        Запись.Записать(СтрФайла);
        
    КонецЦикла;
    
    // Обязательно закрываем файл, чтобы сохранить изменения и освободить блокировку
    Запись.Закрыть();
    
КонецПроцедуры

Резюме

Подводя итог, выделим основные шаги для успешного сохранения файла на сервере:

  1. Определитесь, где будет лежать файл. Используйте локальные пути сервера (например, /opt/1c/tmp/ для Linux или C:\Temp\ для Windows).
  2. Проверьте права доступа служебного пользователя сервера 1С к этой папке.
  3. Для небольших файлов можно использовать ТекстовыйДокумент, для больших отчетов — только ЗаписьТекста.
  4. Учитывайте кодировку (обычно КодировкаТекста.ANSI для CSV под Windows).
  5. Если используете "облачные" решения или Безопасный режим, прямой доступ к дискам может быть запрещен административно.

Применяя эти рекомендации, вы сможете создавать надежные механизмы выгрузки данных, которые не будут перегружать сервер и вызывать ошибки доступа.

← На главную