Файл с компьютера пользователя на сервер 1С: временное хранилище, сетевая папка и HTTP

· 10 мин

Содержание

Чтобы передать файл с клиента на сервер 1С, поместите его во временное хранилище методом НачатьПомещениеФайла (или ПоместитьФайлНаСерверАсинх на новых платформах), а в серверной процедуре заберите его через ПолучитьИзВременногоХранилища(Адрес) — получите объект ДвоичныеДанные, который можно записать на диск сервера или сохранить в базу. Для пакетных обменов без участия пользователя чаще используют общую сетевую папку или HTTP-сервис.

Типичная ситуация: бухгалтер выбирает у себя на компьютере прайс поставщика в Excel, нажимает «Загрузить», а обработка падает с ошибкой «файл не найден». Путь C:\Users\Ivanova\Desktop\price.xlsx существует на её ПК, но серверный код ищет его на сервере 1С, где такого диска и папки нет. Ниже разобрано, как правильно перенести файл с клиента на сервер в клиент-серверной базе и чем отличаются способы.

Где выполняется код: клиент, сервер и файловый режим

В управляемом приложении каждая процедура формы помечена директивой. От неё зависит, на каком компьютере исполняется код и чью файловую систему он видит.

  • 💻 &НаКлиенте — код работает на машине пользователя. Видит его диски, рабочий стол, флешки.
  • 🖥 &НаСервере, &НаСервереБезКонтекста и общие модули с флагом «Сервер» — код работает в рабочем процессе rphost на сервере 1С. Видит только диски сервера и сетевые ресурсы, доступные учётной записи службы.
  • 🔁 Передать файл по ссылке «путь» между ними нельзя. Нужно перенести сами байты.

Для передачи данных между клиентом и сервером платформа даёт временное хранилище. Клиент кладёт туда содержимое файла и получает строковый адрес вида e1cib/tempstorage/.... Адрес — обычная строка, её легко передать параметром в серверную процедуру.

В файловом варианте базы «сервер» физически тот же компьютер, что и клиент. Поэтому код с локальным путём там часто работает, а после перевода базы на сервер 1С ломается. Пишите обработки сразу в расчёте на клиент-серверный режим.

Какой способ выбрать

СпособКогда подходитОграничения
Временное хранилище (НачатьПомещениеФайла)Пользователь сам выбирает файл в формеФайл целиком держится в памяти, неудобно для сотен мегабайт
ДвоичныеДанные параметром серверного вызоваНебольшие файлы, тонкий клиентНе работает в веб-клиенте с путём к файлу
Общая сетевая папкаРегулярный обмен, крупные файлы, роботы-выгрузкиНужны права учётной записи службы 1С на ресурс
HTTP-сервисЗагрузка из внешних систем, сайтов, скриптовНужна публикация базы на веб-сервере
FTPОбмен с контрагентом через его FTPПароль хранится в коде или настройках, без шифрования

Передача файла с клиента на сервер через временное хранилище

Это основной способ для форм и обработок. Он работает в тонком клиенте, веб-клиенте и при запрете модальности.

Пользователь выбирает файл в диалоге

Синхронный метод ПоместитьФайл открывает модальный диалог. В конфигурациях с режимом использования модальности «Не использовать» (все современные типовые) он вызывает ошибку. Используйте асинхронный вариант с описанием оповещения:

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

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

&НаСервере
Процедура ОбработатьФайлНаСервере(Адрес, ИмяФайлаКлиента)
    ДанныеФайла = ПолучитьИзВременногоХранилища(Адрес);
    УдалитьИзВременногоХранилища(Адрес);

    ОписаниеФайла = Новый Файл(ИмяФайлаКлиента);
    ПутьНаСервере = ПолучитьИмяВременногоФайла(Сред(ОписаниеФайла.Расширение, 2));
    ДанныеФайла.Записать(ПутьНаСервере);

    // здесь читаем файл: ТабличныйДокумент, ЧтениеXML, ЧтениеТекста и т.д.

    УдалитьФайлы(ПутьНаСервере);
КонецПроцедуры

Что здесь важно:

  1. Последний параметр — УникальныйИдентификатор формы. Тогда данные живут в хранилище, пока открыта форма. Без него платформа может удалить их раньше, чем серверная процедура успеет их забрать.
  2. Новый Файл(ИмяФайлаКлиента) на сервере ничего не ищет на диске. Он просто разбирает строку и отдаёт расширение .xlsx, а Сред(…, 2) убирает точку.
  3. ПолучитьИмяВременногоФайла возвращает путь во временном каталоге сервера, куда у учётной записи службы гарантированно есть права записи.
  4. Временный файл удаляйте сами. Платформа не чистит его автоматически.

В платформе 8.3.18 и новее тот же сценарий можно написать с ключевыми словами Асинх и Ждать через ПоместитьФайлНаСерверАсинх. Логика не меняется: на выходе тот же адрес во временном хранилище.

Файл с известным путём, без диалога

Если путь задан в настройках обработки, диалог не нужен. Передайте путь третьим параметром и Ложь в параметре «Интерактивно»:

НачатьПомещениеФайла(Оповещение, , "C:\Обмен\price.xlsx", Ложь, УникальныйИдентификатор);

В тонком клиенте это работает сразу. В веб-клиенте неинтерактивное помещение требует установленного расширения работы с файлами: сначала проверьте его через НачатьПодключениеРасширенияРаботыСФайлами, при отсутствии предложите установку методом НачатьУстановкуРасширенияРаботыСФайлами.

Несколько файлов сразу

Для пакетной загрузки есть НачатьПомещениеФайлов. В оповещение приходит массив описаний: у каждого свой адрес во временном хранилище и имя. На сервере обходите массив и для каждого адреса делаете то же, что в примере выше.

Двоичные данные: чтение, запись и хранение на сервере

ДвоичныеДанные — неизменяемый объект с содержимым файла. Его можно передать параметром в серверный вызов, положить в реквизит или записать на диск.

Прямая передача из тонкого клиента

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

&НаКлиенте
Процедура ОтправитьНебольшойФайл(Команда)
    Данные = Новый ДвоичныеДанные("C:\Обмен\act.pdf");
    СохранитьВложениеНаСервере(Данные, "act.pdf");
КонецПроцедуры

Платформа сама сериализует объект при вызове сервера. Для файлов в несколько мегабайт это удобно. Для крупных — нет: весь файл идёт в одном вызове, а форма «подвисает» до его окончания. В веб-клиенте конструктор с путём к файлу недоступен, там остаётся НачатьПомещениеФайла.

Что делать с данными на сервере

  • 📄 Записать на диск: Данные.Записать(Путь). Подходит для последующего разбора внешними средствами.
  • 🗃 Сохранить в базу: реквизит типа ХранилищеЗначения, значение Новый ХранилищеЗначения(Данные, Новый СжатиеДанных(9)). Файл будет в резервных копиях вместе с базой.
  • 🔍 Прочитать без записи на диск: Данные.ОткрытьПотокДляЧтения() даёт поток, его принимают ЧтениеXML, ЧтениеJSON, ЧтениеДанных.
  • 🔐 Проверить целостность: объект ХешированиеДанных с типом ХешФункция.SHA256 позволяет сравнить хеш с присланным отправителем.

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

Передача файла на сервер через сетевую папку

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

Порядок настройки:

  1. Создайте на файловом сервере каталог, например \\fs01\1c-exchange.
  2. Узнайте, под какой учётной записью работает служба «Агент сервера 1С:Предприятия». По умолчанию это локальный пользователь USR1CV8, в домене часто заводят отдельную доменную учётку.
  3. Дайте этой учётной записи права чтения и записи на общий ресурс и на NTFS-папку. Пользователям — только запись.
  4. В коде используйте UNC-путь \\fs01\1c-exchange\, а не букву сетевого диска.

На клиенте файл копируют так:

КопироватьФайл("C:\Обмен\price.xlsx", "\\fs01\1c-exchange\price.xlsx");

Если в конфигурации запрещены синхронные вызовы расширений платформы, замените его на НачатьКопированиеФайла с описанием оповещения.

Буквы подключённых сетевых дисков (Z:, S:) существуют только в сеансе вошедшего пользователя. Служба 1С работает без интерактивного входа, поэтому для неё диска Z: нет. Это самая частая причина ошибки «файл не найден» при правильном, казалось бы, пути.

На сервере 1С под Linux общий ресурс монтируют через cifs в каталог, например /mnt/1c-exchange, и дают права пользователю usr1cv8. В коде тогда указывается путь Linux, а не UNC.

Чтобы два процесса не начали разбирать один файл одновременно, клиент пусть пишет файл с расширением .tmp, а по окончании переименовывает. Регламентное задание на сервере берёт только готовые файлы и после обработки переносит их в подпапку done.

Загрузка файлов на сервер 1С через HTTP-сервис

HTTP-сервис нужен, когда файл приходит не из формы 1С: с сайта, из мобильного приложения, из скрипта на складе. Сервис принимает POST-запрос с файлом в теле и сам решает, что с ним делать.

Создание и публикация

  1. В Конфигураторе в ветке Общие → HTTP-сервисы добавьте сервис, задайте корневой URL, например files.
  2. Добавьте шаблон URL /upload/{name} и метод POST. Конфигуратор создаст обработчик в модуле сервиса.
  3. Опубликуйте базу на веб-сервере (Apache или IIS) через Администрирование → Публикация на веб-сервере и включите флажок публикации HTTP-сервисов.
  4. Адрес сервиса будет вида http://srv/base/hs/files/upload/price.xlsx.

Обработчик:

Функция UploadPOST(Запрос)
    Данные = Запрос.ПолучитьТелоКакДвоичныеДанные();
    Если Данные.Размер() = 0 Тогда
        Ответ = Новый HTTPСервисОтвет(400);
        Ответ.УстановитьТелоИзСтроки("Пустое тело запроса");
        Возврат Ответ;
    КонецЕсли;

    ИмяИсходное = Запрос.ПараметрыURL["name"];
    ОписаниеФайла = Новый Файл(ИмяИсходное);
    ПутьНаСервере = ПолучитьИмяВременногоФайла(Сред(ОписаниеФайла.Расширение, 2));
    Данные.Записать(ПутьНаСервере);

    // разбор файла или постановка в очередь на обработку

    Возврат Новый HTTPСервисОтвет(200);
КонецФункции

Имя файла из URL не используйте как путь напрямую. Строка вида ..\..\Windows\… позволит записать файл куда угодно. Берите из неё только расширение или сохраняйте под сгенерированным именем.

Проверить сервис можно утилитой curl:

curl -u exchange:Пароль -X POST --data-binary @price.xlsx http://srv/base/hs/files/upload/price.xlsx

Запрос выполняется от имени пользователя 1С, указанного в -u. Заведите для обмена отдельного пользователя с минимальной ролью, а не администратора.

Отправка из другой базы 1С

Если файл нужно передать из одной базы 1С в другую, на стороне отправителя используют HTTPСоединение и HTTPЗапрос. Метод УстановитьИмяФайлаТела берёт тело прямо из файла, не загружая его в память целиком, — это удобно для крупных выгрузок.

Передача файла по FTP

FTP пригождается, когда контрагент или собственный сайт принимает файлы только так. В 1С для этого есть объект FTPСоединение, он работает на сервере и на клиенте.

Соединение = Новый FTPСоединение("ftp.example.ru", 21, "user", "Пароль", , Истина);
Соединение.Записать(ПутьНаСервере, "/incoming/price.xlsx");

Шестой параметр включает пассивный режим — без него соединение часто не проходит через сетевой экран. Пароль не держите в тексте модуля: храните его в защищённом хранилище или в константе с ограниченным доступом.

  • 🔒 Обычный FTP передаёт логин и файл открытым текстом. Для чувствительных данных конструктор принимает объект ЗащищенноеСоединениеOpenSSL.
  • 🧾 Чтобы получить файл с FTP на сервер 1С, используется метод Получить с теми же параметрами в обратном порядке: путь на FTP, затем локальный путь.

Ошибки при передаче файлов и журнал регистрации

Обмен файлами ломается на правах, путях и размерах. Оборачивайте работу с файлом на сервере в Попытка … Исключение и пишите причину в журнал регистрации:

Попытка
    ДанныеФайла.Записать(ПутьНаСервере);
Исключение
    ЗаписьЖурналаРегистрации("Обмен.ЗагрузкаФайла",
        УровеньЖурналаРегистрации.Ошибка, , ,
        ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    ВызватьИсключение "Не удалось сохранить файл на сервере. Подробности в журнале регистрации.";
КонецПопытки;

Своё имя события (Обмен.ЗагрузкаФайла) позволяет отфильтровать записи в журнале по событию и быстро найти все сбои загрузки. В регламентных заданиях это единственный способ узнать, что пошло не так: пользователя, которому можно показать сообщение, там нет.

Диагностика: выберите симптом

Частые вопросы

Есть ли ограничение на размер файла во временном хранилище?
Жёсткого лимита в платформе нет, но файл целиком размещается в памяти рабочего процесса сервера. Файлы в сотни мегабайт надёжнее передавать через сетевую папку или HTTP.
Можно ли передать файл с сервера обратно на клиент?
Да, обратным путём: на сервере ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор), на клиенте — НачатьПолучениеФайлов с описанием этого адреса. Пользователь увидит диалог сохранения.
Работает ли НачатьПомещениеФайла в веб-клиенте без расширения работы с файлами?
Работает только в интерактивном режиме: пользователь сам выбирает файл в диалоге браузера. Чтение по заданному пути без диалога требует расширения.
Почему в файловой базе всё работало, а на сервере перестало?
В файловом режиме серверный код исполняется на том же компьютере, что и клиент, и видит его диски. На сервере 1С код работает на другой машине под учётной записью службы.
Под каким пользователем сервер 1С обращается к сетевой папке?
Под учётной записью, от которой запущена служба агента сервера, а не под пользователем 1С и не под тем, кто вошёл в Windows на клиенте.