Разберем распространенную проблему, с которой сталкиваются разработчики при интеграции 1С с внешними системами: ситуация, когда файл по ссылке скачивается не полностью или «рандомно» обрывается. Например, вместо ожидаемых 30 000 записей в итоговом файле оказывается всего 500. Проанализируем причины такого поведения и рассмотрим несколько способов реализации загрузки — от классических COM-объектов до современных нативных методов 1С.
Прежде чем переходить к коду, выясним причину нестабильности. Чаще всего проблема кроется в использовании старых технологий, таких как WinHttp.WinHttpRequest.5.1 в связке с ADODB.Stream. При работе с большими объемами данных (от 20 МБ и выше) эти объекты могут вести себя непредсказуемо по следующим причинам:
WaitForResponse) может приводить к преждевременному закрытию потока.Рассмотрим по шагам, как можно реализовать задачу загрузки более надежными способами.
Если архитектура решения требует использования именно 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. Текстовое свойство пытается интерпретировать байты как символы, что при наличии бинарных данных или специфических кодировок приводит к «обрезанию» файла на первом же встреченном спецсимволе или ошибке преобразования.
Проанализируем самый простой и зачастую самый быстрый метод — использование встроенной функции глобального контекста КопироватьФайл. Она поддерживает протоколы http, https и ftp.
Этот метод хорош тем, что 1С сама берет на себя управление потоками и буферизацией данных, что минимизирует риск неполной загрузки файла.
// Определяем адрес источника и путь назначения
АдресФайла = "https://server.ru/price.csv";
ВременныйФайл = ПолучитьИмяВременногоФайла("csv");
Попытка
// Важно: используйте прямые слеши в URL
КопироватьФайл(АдресФайла, ВременныйФайл);
Сообщить("Файл скачан успешно!");
Исключение
Сообщить("Не удалось получить файл: " + ОписаниеОшибки());
КонецПопытки;
Однако у этого метода есть ограничение: вы не можете передать авторизационные заголовки или специфические headers (например, User-Agent). Если сервер требует авторизации, этот способ не подойдет.
В современных конфигурациях (УТ 11, ERP, БП 3.0) разработчики 1С уже предусмотрели надежные механизмы для работы с интернетом. Рассмотрим использование модуля ПолучениеФайловИзИнтернета. Этот метод является наиболее предпочтительным, так как он корректно обрабатывает прокси-серверы и ошибки соединения.
URL = "https://provider.com/data.csv";
// Скачиваем файл во временное хранилище
Результат = ПолучениеФайловИзИнтернета.СкачатьФайлВоВременноеХранилище(URL);
Если Результат.Статус Тогда
ДанныеФайла = ПолучитьИзВременногоХранилища(Результат.Путь);
ИмяФайла = ПолучитьИмяВременногоФайла("csv");
ДанныеФайла.Записать(ИмяФайла);
Сообщить("Файл получен и сохранен в: " + ИмяФайла);
Иначе
Сообщить("Ошибка при загрузке: " + Результат.СообщениеОбОшибке);
КонецЕсли;
После того как мы обеспечили стабильное получение файла, его необходимо правильно прочитать. Если вы работаете с CSV-файлами большого объема, рекомендуется использовать объект ЧтениеТекста, чтобы не перегружать оперативную память:
ЧтениеТекста, указывая кодировку (например, КодировкаТекста.UTF8).ПрочитатьСтроку().СтрРазделить(), указав разделитель (запятая, точка с запятой или табуляция).Резюме: Если вы столкнулись с «рандомной» обрезкой файла, первым делом откажитесь от использования COM-объектов в пользу нативных средств 1С (HTTPСоединение или КопироватьФайл). Это обеспечит кроссплатформенность вашего кода и более высокую стабильность при работе с файлами любого размера.