Как отправить несколько файлов через ADODB.Stream в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При разработке механизмов обмена данными в среде 1С 7.7 программисты часто сталкиваются с необходимостью передачи файлов на веб-сервер. Использование связки ADODB.Stream и XMLHTTP является классическим решением, однако при попытке отправить несколько файлов возникает методическая сложность. Метод loadFromFile объекта ADODB.Stream при повторном вызове просто перезаписывает содержимое потока, что делает невозможным прямую «склейку» файлов простым перебором.

В этой статье мы разберем несколько стратегий решения этой задачи: от наиболее простого способа с архивацией до технически сложного формирования многокомпонентного запроса (multipart/form-data).

Метод 1. Архивация файлов перед отправкой

Это самый надежный и простой в реализации способ, предложенный участниками форума. Вместо того чтобы пытаться передать коллекцию отдельных файлов, мы упаковываем их в один архив (например, ZIP) и передаем этот архив как один бинарный объект. Рассмотрим, как это сделать с помощью популярной библиотеки 1С++ и класса BinaryData.

Для работы нам потребуется внешняя компонента 1cpp.dll. Разберем пример кода для создания архива:


// Создаем объект для работы с бинарными данными
БинДанные = СоздатьОбъект("BinaryData");

// Формируем строку с путями к файлам. 
// Если пути содержат пробелы, обязательно заключаем их в кавычки.
СписокФайлов = """C:\Data\Report1.xml"" ""C:\Data\Image2.jpg""";
ПутьКАрхиву = "C:\Data\Upload.zip";

// Используем метод Zip. Синтаксис: Zip(КоманднаяСтрока)
// Ключ -s может использоваться для установки пароля, если это необходимо.
Результат = БинДанные.Zip(ПутьКАрхиву + " " + СписокФайлов);

Если Результат = 1 Тогда
    Сообщить("Архив успешно создан");
Иначе
    Сообщить("Ошибка при архивации");
КонецЕсли;

После создания архива мы можем стандартным образом загрузить его в ADODB.Stream и отправить через XMLHTTP:


Данные = СоздатьОбъект("ADODB.Stream");
Данные.Type = 1; // Binary
Данные.Open();
Данные.LoadFromFile(ПутьКАрхиву);

Http = СоздатьОбъект("MSXML2.XMLHTTP");
Http.Open("POST", "http://your-server.com/upload", 0);
Http.Send(Данные);

Важный нюанс: при использовании командной строки через 1С++ или внешние архиваторы (7-Zip, WinRAR), разделяйте пути к файлам пробелами. Если файлов много, убедитесь, что длина командной строки не превышает системные ограничения Windows.

Метод 2. Использование метода CopyTo для склеивания потоков

Если по каким-то причинам архивация недопустима, мы можем попытаться объединить данные в одном объекте ADODB.Stream вручную. Для этого проанализируем возможности метода CopyTo. Основная идея заключается в том, чтобы открывать каждый файл в отдельном временном потоке и копировать его содержимое в основной поток.

Разберем алгоритм по шагам:

  1. Создаем основной поток MainStream, где будут накапливаться данные.
  2. В цикле создаем временный поток TempStream.
  3. Загружаем файл во временный поток через LoadFromFile.
  4. Копируем содержимое временного потока в основной.
  5. Сбрасываем позицию в основном потоке для следующей записи, если это необходимо.

Однако помните, что простая склейка бинарных данных без разделителей приведет к тому, что на сервере вы получите один «кашеобразный» файл. Этот метод подходит только в том случае, если принимающая сторона точно знает структуру и размеры каждого блока данных.

Метод 3. Формирование запроса Multipart/form-data

Это наиболее «правильный» с точки зрения веб-технологий способ. Он позволяет передать несколько файлов так, как это делает обычная HTML-форма. Структура такого запроса подразумевает наличие специального разделителя (boundary), который отделяет один файл от другого и от текстовых полей.

Проанализируем техническую сложность: в 1С 7.7 работа с бинарными данными ограничена. Основная проблема — объединение текстовых заголовков (Content-Disposition) и бинарного тела файла. В одном объекте ADODB.Stream нельзя просто переключаться между WriteText (для заголовков) и Write (для бинарных данных) без риска повреждения кодировки.

Для реализации этого подхода часто используют вспомогательные функции преобразования строки в SafeArray или используют объект Recordset для сборки байтов. Рассмотрим схематично структуру, которую нужно сформировать в потоке:


--Разделитель_Граница
Content-Disposition: form-data; name="file1"; filename="data1.txt"
Content-Type: text/plain

[Бинарные данные файла 1]
--Разделитель_Граница
Content-Disposition: form-data; name="file2"; filename="data2.jpg"
Content-Type: image/jpeg

[Бинарные данные файла 2]
--Разделитель_Граница--

Метод 4. Передача через Base64 внутри XML

Если вы контролируете и отправку, и прием данных, мы рекомендуем рассмотреть вариант упаковки файлов в XML-пакет в кодировке Base64. Это снимет все вопросы с бинарной склейкой.

Выясним причину популярности этого метода: XML-документ может содержать неограниченное количество узлов, в каждом из которых будет лежать строка Base64, представляющая отдельный файл. В 1С 7.7 для быстрой конвертации удобно использовать возможности MSXML2.DOMDocument:


// Создаем узел с типом bin.base64 для автоматической конвертации
Дом = СоздатьОбъект("MSXML2.DOMDocument");
Узел = Дом.createElement("file_data");
Узел.dataType = "bin.base64";

// Загружаем данные из ADODB.Stream в узел
Поток = СоздатьОбъект("ADODB.Stream");
Поток.Type = 1;
Поток.Open();
Поток.LoadFromFile("C:\path\to\file.ext");
Узел.nodeTypedValue = Поток.Read();

// Теперь Узел.text содержит файл в формате Base64

Выбор программного объекта: XMLHTTP или WinHTTP?

В сообщении упоминается XMLHTTP. Однако в контексте 1С 7.7 мы советуем использовать WinHttp.WinHttpRequest.5.1. Рассмотрим подробнее преимущества этого объекта:

Ограничения и рекомендации

При работе с ADODB.Stream в 1С 7.7 важно помнить о памяти. Поскольку 7.7 является 32-битным приложением, попытка загрузить в один поток файлы общим объемом более 200–500 Мб может привести к ошибке Out of Memory. Если вам нужно передать очень большой объем данных, лучше использовать пофайловую отправку в цикле, делая отдельный HTTP-запрос для каждого файла.

Подведем итог: если ваша цель — быстро и надежно отправить группу файлов, используйте архивацию. Если требуется строгое соответствие протоколам веб-сервера без использования архивов, готовьтесь к реализации multipart/form-data с использованием низкоуровневых манипуляций бинарными данными.

← На главную