При интеграции различных информационных систем на базе «1С:Предприятие» часто возникает задача программной передачи файлов. Одной из наиболее распространенных технологий для этого является COM-соединение. Однако начинающие разработчики часто сталкиваются с тем, что файл «не доходит» или не сохраняется в целевой базе, даже если код кажется логически верным. В данной статье мы подробно разберем, как правильно передать файл Excel (или любой другой двоичный файл) через COM-интерфейс, проанализируем типичные ошибки и рассмотрим альтернативные методы обеспечения надежности передачи.
Рассмотрим типичную ситуацию. Программист пытается создать объект в другой базе через COM-соединение и передать туда данные. Ошибка часто заключается в использовании неправильного типа данных. Посмотрим на пример кода, который не работает:
// ОШИБОЧНЫЙ КОД
двДанные = СОМСервер.NewObject("Файл", ПолныйПутьКФайлу);
СпрУПП.Хранилище = СОМСервер.NewObject("ХранилищеЗначения", двДанные);
Давайте выясним причину неудачи. Объект Файл в системе 1С предназначен для получения метаданных о файле: его размера, расширения, даты изменения или проверки его существования. Он не содержит в себе самого содержимого файла (его байтов). Когда мы передаем такой объект в ХранилищеЗначения, мы записываем информацию о пути к файлу, но не сам файл. Чтобы передать содержимое, нам необходим объект ДвоичныеДанные.
Для успешной загрузки Excel-файла в справочник «ХранилищеДополнительнойИнформации» (или аналогичный) в целевой базе, необходимо инициализировать объект ДвоичныеДанные внутри контекста COM-соединения. Разберем правильный алгоритм действий по шагам.
ДвоичныеДанные, указав путь к файлу.ХранилищеЗначения.Проанализируем исправленный код, который успешно решает задачу:
СпрУПП = СОМСервер.Справочники.ХранилищеДополнительнойИнформации.СоздатьЭлемент();
СпрУПП.Объект = ДокУПП.Ссылка;
СпрУПП.ВидДанных = СОМСервер.Перечисления.ВидыДополнительнойИнформацииОбъектов.Файл;
СпрУПП.ИмяФайла = "" + КраткоеИмяФайла + ".xlsx";
// Правильное создание двоичных данных в контексте COM
двДанные = СОМСервер.NewObject("ДвоичныеДанные", ПолныйПутьКФайлу);
// Помещение данных в хранилище с использованием конструктора целевой базы
СпрУПП.Хранилище = СОМСервер.NewObject("ХранилищеЗначения", двДанные);
СпрУПП.Записать();
Важный момент: при вызове СОМСервер.NewObject первым параметром передается имя типа в виде строки, а последующими — параметры, которые обычно указываются при использовании стандартного оператора Новый. Обратите внимание, что объект ДвоичныеДанные должен быть создан именно через СОМСервер, чтобы он был «родным» для той базы, в которую идет запись.
При использовании метода СОМСервер.NewObject("ДвоичныеДанные", ПолныйПутьКФайлу) мы должны учитывать физическое расположение файла. Если ваша база работает в клиент-серверном варианте, выполнение кода может происходить на сервере 1С. В этом случае путь ПолныйПутьКФайлу должен указывать на ресурс, доступный именно серверу (службе rphost), а не вашему локальному компьютеру.
Если файл находится на вашем компьютере, а COM-соединение инициируется сервером, система выдаст ошибку «Файл не найден». В таких случаях рекомендуется сначала копировать файл в общую сетевую папку или использовать передачу данных через строку.
Если возникают сложности с правами доступа к файловой системе между серверами, проанализируем более универсальный способ — передачу файла в виде текстовой строки формата Base64. Этот метод позволяет передать содержимое файла непосредственно внутри COM-вызова без обращения к дискам в целевой базе.
Рассмотрим реализацию этого метода:
// В исходной базе преобразуем файл в строку
ФайлДвоичныеДанные = Новый ДвоичныеДанные(ПолныйПутьКФайлу);
СтрокаBase64 = Base64Строка(ФайлДвоичныеДанные);
// В целевой базе через COM восстанавливаем данные из строки
ДвоичныеДанныеДляПриемника = СОМСервер.Base64Значение(СтрокаBase64);
// Далее работаем как обычно
СпрУПП.Хранилище = СОМСервер.NewObject("ХранилищеЗначения", ДвоичныеДанныеДляПриемника);
Преимущество этого подхода в том, что передается сама информация, а не ссылка на файл. Однако помните, что преобразование в Base64 увеличивает объем передаваемых данных примерно на 33%, что может быть критично для очень больших Excel-файлов (сотни мегабайт).
При записи данных в ХранилищеЗначения через COM можно использовать дополнительный параметр — СжатиеДанных. Посмотрим на пример:
Сжатие = СОМСервер.NewObject("СжатиеДанных", 9); // Максимальное сжатие
СпрУПП.Хранилище = СОМСервер.NewObject("ХранилищеЗначения", двДанные, Сжатие);
Но стоит ли это делать для Excel-файлов? Проанализируем структуру файлов .xlsx. Современные файлы Excel по сути являются zip-архивами. Повторное сжатие уже сжатых данных средствами 1С практически не уменьшит размер файла, но создаст дополнительную нагрузку на процессор при записи и последующем чтении. Поэтому для файлов .xlsx, .docx, .png или .zip сжатие в ХранилищеЗначения лучше не использовать или устанавливать уровень 0.
Подведем итоги нашего исследования. Для успешной передачи файлов через COM-соединение:
ДвоичныеДанные, а не Файл.ДвоичныеДанные и ХранилищеЗначения через метод NewObject вашего COM-соединения.Base64.Соблюдение этих правил позволит вам создавать стабильные и производительные механизмы обмена данными между базами 1С.