Как передать файл из одной базы 1С в другую через веб-сервисы или JSON без ошибок доступа?

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

Перенос присоединенных файлов между различными информационными базами 1С — одна из наиболее частых задач при построении интеграционных решений. На первый взгляд алгоритм выглядит просто: выгрузить файл во временный каталог на стороне отправителя, передать по каналам связи и загрузить в справочник присоединенных файлов на стороне получателя. Однако на практике разработчики регулярно сталкиваются с неочевидными системными ошибками, такими как «Отказано в доступе (0x00000005)», повреждением структуры файлов при передаче, а также сбоями при попытке прикрепить файл к документам БСП (Библиотеки Стандартных Подсистем). Для решения подобных интеграционных задач можно использовать готовый инструмент для обмена файлами и данными между базами 1С.

В этой статье мы подробно разберем все этапы реализации надежного обмена файлами, выясним причины возникновения системных ошибок файловой системы и напишем готовый к использованию код для передачи данных через веб-сервисы и JSON-пакеты.

---

Раздел 1. Анализ и решение проблемы «Ошибка доступа к файлу... (0x00000005)»

Рассмотрим ситуацию, с которой часто сталкиваются начинающие разработчики. При попытке сохранить двоичные данные из хранилища значений на диск с помощью кода:


Путь = "D:\NewFile"; 
Хранилище = Выборка.ФайлХранилище.Получить(); 
Хранилище.Записать(Путь);

Система возвращает ошибку: «Ошибка доступа к файлу... 5(0x00000005): Отказано в доступе». Проанализируем причины этой проблемы. Их две:

  1. Передача пути к каталогу вместо файла. Метод Записать() объекта ДвоичныеДанные (или ХранилищеЗначения) ожидает получить полный путь к конечному файлу, включая его имя и расширение (например, "D:\NewFile\contract.pdf"). Если указать только путь к каталогу, операционная система заблокирует операцию записи, выдав ошибку доступа.
  2. Недостаток прав у учетной записи сервера 1С. Любой код, выполняющийся в фоновом задании, на веб-сервисе или в серверном модуле, отрабатывает в контексте операционной системы под учетной записью, под которой запущена служба сервера 1С:Предприятие (обычно это USR1CV8 или NetworkService). По умолчанию у этих пользователей нет прав на запись в корень дисков (например, D:\) или в личные папки пользователей Windows.

Как правильно работать с временными путями в 1С:

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

Посмотрим на пример правильного извлечения файла во временный каталог:


// Получаем расширение оригинального файла (например, "pdf" или "docx")
Расширение = Выборка.РасширениеФайла; 

// Генерируем безопасный путь во временном каталоге сервера
ПутьКВременномуФайлу = ПолучитьИмяВременногоФайла(Расширение);

// Извлекаем двоичные данные из хранилища значений
ДвоичныеДанныеФайла = Выборка.ФайлХранилище.Получить();

Если ТипЗнч(ДвоичныеДанныеФайла) = Тип("ДвоичныеДанные") Тогда
    // Записываем файл на диск по безопасному пути
    ДвоичныеДанныеФайла.Записать(ПутьКВременномуФайлу);
ИначеЕсли ТипЗнч(ДвоичныеДанныеФайла) = Тип("ХранилищеЗначения") Тогда
    ДвоичныеДанныеФайла.Получить().Записать(ПутьКВременномуФайлу);
КонецЕсли;

---

Раздел 2. Передача файла между базами через HTTP (Base64 и JSON)

Передать бинарный файл «как есть» напрямую внутри текстового формата JSON невозможно. Для этого бинарные данные необходимо закодировать в текстовую строку. Стандартом для таких операций является кодирование в **Base64**.

Выясним, как выглядит процесс передачи файла «База-Отправитель -> JSON -> База-Получатель»:

Шаг 1. Подготовка и кодирование файла на стороне базы-отправителя

Нам необходимо считать файл с диска в объект ДвоичныеДанные, перевести его в формат Base64 и упаковать в структуру JSON для последующей передачи через HTTP-запрос или веб-сервис.


Функция СформироватьПакетДанныхФайла(ПутьКФайлу, ИмяФайла, Расширение) Экспорт
    
    // Читаем файл в двоичные данные
    ФайлДД = Новый ДвоичныеДанные(ПутьКФайлу);
    
    // Кодируем двоичные данные в текстовую строку Base64
    СтрокаBase64 = Base64Строка(ФайлДД);
    
    // Формируем структуру для сериализации в JSON
    СтруктураПакета = Новый Структура;
    СтруктураПакета.Вставить("ИмяФайла", ИмяФайла);
    СтруктураПакета.Вставить("Расширение", Расширение);
    СтруктураПакета.Вставить("ДанныеФайластрокой", СтрокаBase64);
    
    // Записываем структуру в JSON
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, СтруктураПакета);
    
    Возврат ЗаписьJSON.Закрыть();
    
КонецФункции

Шаг 2. Декодирование и воссоздание файла на стороне базы-получателя

Когда база-получатель принимает JSON-пакет, она должна выполнить обратное преобразование: прочитать строку Base64 и преобразовать ее в объект ДвоичныеДанные.


Процедура ПринятьИСохранитьФайлИзJSON(СтрокаJSON) Экспорт
    
    // Читаем входящий JSON-пакет
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
    
    ДанныеПакета = ПрочитатьJSON(ЧтениеJSON);
    ЧтениеJSON.Закрыть();
    
    ИмяФайла = ДанныеПакета.ИмяФайла;
    Расширение = ДанныеПакета.Расширение;
    СтрокаBase64 = ДанныеПакета.ДанныеФайластрокой;
    
    // Декодируем строку Base64 обратно в двоичные данные
    ДвоичныеДанныеФайла = Base64Значение(СтрокаBase64);
    
    // Теперь у нас есть чистый объект ДвоичныеДанные, готовый к записи
    ПутьДляСохранения = ПолучитьИмяВременногоФайла(Расширение);
    ДвоичныеДанныеФайла.Записать(ПутьДляСохранения);
    
    // Дальнейшая логика прикрепления файла к объекту базы...
    
КонецПроцедуры

Важное предупреждение по производительности: Кодирование файлов в Base64 увеличивает размер передаваемых данных примерно на 33%. Если вам необходимо передавать файлы размером более 50-100 МБ, рекомендуется использовать прямую передачу бинарных потоков через HTTP-сервисы (заголовки Content-Type: application/octet-stream) без кодирования в текст.

---

Раздел 3. Правильная интеграция файлов с механизмами БСП (Библиотека Стандартных Подсистем)

Разберем типичную ошибку архитектуры, упомянутую в обсуждении. Попытка записать двоичные данные напрямую в реквизит ХранилищеДанных справочника присоединенных файлов (например, Справочник.ДокументыПрисоединенныеФайлы) часто приводит к тому, что файлы перестают открываться пользователями или вызывают критические ошибки системы.

Почему прямая запись в реквизит недопустима в БСП?

Современные конфигурации 1С (ERP, КА, УТ, БП, ЗУП) используют стандартные механизмы подсистемы «Работа с файлами». В зависимости от настроек программы, файлы могут храниться:

Если в системе включено хранение файлов в томах на диске, прямая запись данных в реквизит ХранилищеДанных приведет к нарушению целостности системы. Справочник создаст карточку файла, но самого физического файла на диске не окажется. Кроме того, при ручном создании элемента справочника не регистрируются обязательные метаданные: размер файла, его автор, расширение, статус проверки на вирусы и хэш-сумма.

Чтобы избежать подобных проблем, используйте программный интерфейс БСП — общий модуль РаботаСФайлами. Рассмотрим пошаговый алгоритм добавления полученного файла к документу-приемнику:


Процедура ПрикрепитьФайлКДокументуБСП(ДвоичныеДанныеФайла, СсылкаНаДокумент, ИмяФайла, Расширение)
    
    // Шаг 1. Помещаем двоичные данные во временное хранилище 1С
    АдресВременногоХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла);
    
    // Шаг 2. Инициализируем структуру параметров для добавления файла через БСП
    ПараметрыФайла = РаботаСФайлами.ПараметрыДобавленияФайла();
    ПараметрыФайла.Автор = Пользователи.ТекущийПользователь();
    
    // Указываем владельца файла (документ, справочник или бизнес-процесс)
    ПараметрыФайла.ВладелецФайлов = СсылкаНаДокумент; 
    
    // Настраиваем имя и расширение
    ПараметрыФайла.ИмяБезРасширения = ИмяФайла;
    ПараметрыФайла.РасширениеБезТочки = Расширение;
    
    // Шаг 3. Вызываем стандартную процедуру БСП для автоматического создания элемента
    // Она сама определит, куда положить файл (в базу или на том), посчитает размер и свяжет с документом
    РезультатДобавления = РаботаСФайлами.ДобавитьФайл(ПараметрыФайла, АдресВременногоХранилища);
    
    Если РезультатДобавления.ФайлДобавлен Тогда
        ЗаписатьЛогСобытия("Файл успешно прикреплен к документу: " + Строка(СсылкаНаДокумент));
    Иначе
        ВызватьИсключение "Не удалось прикрепить файл средствами БСП: " + РезультатДобавления.ТекстОшибки;
    КонецЕсли;
    
КонецПроцедуры

---

Резюме и чеклист для разработчика

Для создания отказоустойчивого механизма обмена файлами между базами 1С всегда следуйте этим правилам:

  1. При работе с локальными дисками на сервере никогда не прописывайте пути вручную. Всегда используйте метод ПолучитьИмяВременногоФайла().
  2. Если обмен идет через REST, SOAP или HTTP-сервисы с использованием JSON или XML, обязательно кодируйте бинарные файлы в строку **Base64** с помощью встроенных функций 1С Base64Строка() и Base64Значение().
  3. Никогда не записывайте данные напрямую в реквизиты справочников присоединенных файлов. Всегда делегируйте эту работу программному интерфейсу БСП через общий модуль РаботаСФайлами. Это гарантирует корректное распределение файлов по сетевым томам и корректное заполнение системных метаданных.
← На главную