Как правильно скачать файл по прямой ссылке в 1С, чтобы он загружался полностью?

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

Разберем распространенную проблему, с которой сталкиваются разработчики при интеграции 1С с внешними системами: ситуация, когда файл по ссылке скачивается не полностью или «рандомно» обрывается. Например, вместо ожидаемых 30 000 записей в итоговом файле оказывается всего 500. Проанализируем причины такого поведения и рассмотрим несколько способов реализации загрузки — от классических COM-объектов до современных нативных методов 1С.

Почему файл скачивается не полностью?

Прежде чем переходить к коду, выясним причину нестабильности. Чаще всего проблема кроется в использовании старых технологий, таких как WinHttp.WinHttpRequest.5.1 в связке с ADODB.Stream. При работе с большими объемами данных (от 20 МБ и выше) эти объекты могут вести себя непредсказуемо по следующим причинам:

  1. Смешение режимов: Попытка одновременно использовать асинхронный вызов и методы ожидания (WaitForResponse) может приводить к преждевременному закрытию потока.
  2. Ограничения буфера: COM-объекты работают через системные библиотеки Windows, которые могут иметь внутренние ограничения на объем передаваемых данных в памяти.
  3. Проблемы окружения: Как было замечено в обсуждении, на работу этих объектов могут влиять настройки конкретной операционной системы, антивирусы или версии платформы 1С.

Рассмотрим по шагам, как можно реализовать задачу загрузки более надежными способами.

Способ 1. Использование объекта WinHttp (исправленный вариант)

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


WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
// Устанавливаем кодировку и параметры соединения
WinHttp.Option(2, "utf-8"); 

// Открываем соединение в синхронном режиме (Ложь)
WinHttp.Open("GET", "http://example.com/file.csv", Ложь);
WinHttp.Send();

// Ждем ответа от сервера (таймаут в миллисекундах)
WinHttp.WaitForResponse(120000);

Если WinHttp.Status = 200 Тогда
    // Используем ADODB.Stream для сохранения бинарных данных
    Stream = Новый COMОбъект("ADODB.Stream");
    Stream.Type = 1; // Тип - бинарный
    Stream.Mode = 3; // Доступ - чтение/запись
    
    ПутьКФайлу = ПолучитьИмяВременногоФайла("csv");
    
    Stream.Open();
    // Крайне важно использовать ResponseBody, а не ResponseText для файлов
    Stream.Write(WinHttp.ResponseBody);
    Stream.SaveToFile(ПутьКФайлу, 2); // 2 - перезаписать файл
    Stream.Close();
    
    Сообщить("Файл успешно сохранен: " + ПутьКФайлу);
Иначе
    Сообщить("Ошибка HTTP: " + WinHttp.Status + " " + WinHttp.StatusText);
КонецЕсли;

Важный нюанс: Обратите внимание на использование WinHttp.ResponseBody. Многие совершают ошибку, пытаясь сохранить WinHttp.ResponseText. Текстовое свойство пытается интерпретировать байты как символы, что при наличии бинарных данных или специфических кодировок приводит к «обрезанию» файла на первом же встреченном спецсимволе или ошибке преобразования.

Способ 2. Системная функция КопироватьФайл

Проанализируем самый простой и зачастую самый быстрый метод — использование встроенной функции глобального контекста КопироватьФайл. Она поддерживает протоколы http, https и ftp.

Этот метод хорош тем, что 1С сама берет на себя управление потоками и буферизацией данных, что минимизирует риск неполной загрузки файла.


// Определяем адрес источника и путь назначения
АдресФайла = "https://server.ru/price.csv";
ВременныйФайл = ПолучитьИмяВременногоФайла("csv");

Попытка
    // Важно: используйте прямые слеши в URL
    КопироватьФайл(АдресФайла, ВременныйФайл);
    Сообщить("Файл скачан успешно!");
Исключение
    Сообщить("Не удалось получить файл: " + ОписаниеОшибки());
КонецПопытки;

Однако у этого метода есть ограничение: вы не можете передать авторизационные заголовки или специфические headers (например, User-Agent). Если сервер требует авторизации, этот способ не подойдет.

Способ 3. Использование типовых подсистем (БСП)

В современных конфигурациях (УТ 11, ERP, БП 3.0) разработчики 1С уже предусмотрели надежные механизмы для работы с интернетом. Рассмотрим использование модуля ПолучениеФайловИзИнтернета. Этот метод является наиболее предпочтительным, так как он корректно обрабатывает прокси-серверы и ошибки соединения.


URL = "https://provider.com/data.csv";
// Скачиваем файл во временное хранилище
Результат = ПолучениеФайловИзИнтернета.СкачатьФайлВоВременноеХранилище(URL);

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

Рекомендации по обработке скачанного файла

После того как мы обеспечили стабильное получение файла, его необходимо правильно прочитать. Если вы работаете с CSV-файлами большого объема, рекомендуется использовать объект ЧтениеТекста, чтобы не перегружать оперативную память:

  1. Создаем объект ЧтениеТекста, указывая кодировку (например, КодировкаТекста.UTF8).
  2. Читаем файл построчно в цикле с помощью метода ПрочитатьСтроку().
  3. Для разбиения строки на колонки используем функцию СтрРазделить(), указав разделитель (запятая, точка с запятой или табуляция).

Резюме: Если вы столкнулись с «рандомной» обрезкой файла, первым делом откажитесь от использования COM-объектов в пользу нативных средств 1С (HTTPСоединение или КопироватьФайл). Это обеспечит кроссплатформенность вашего кода и более высокую стабильность при работе с файлами любого размера.

← На главную