В процессе автоматизации обмена данными через FTP-протокол программисты 1С часто сталкиваются с проблемой "битых" файлов. Это ситуация, когда соединение разрывается в процессе передачи, и на диске остается лишь часть данных, при этом система может не выдать явной ошибки. В этой статье мы подробно разберем, как гарантированно определить, что файл скачан полностью и готов к обработке.
Прежде чем перейти к решениям, проанализируем ситуацию. Стандартный метод 1С FTPСоединение.Получить() в большинстве случаев корректно обрабатывает ошибки сети. Однако существуют сценарии (особенно на нестабильных каналах или при специфических настройках прокси-серверов), когда файл создается на диске, заполняется частично, и процесс завершается без исключения. Также возможна ситуация, когда внешняя система начала загрузку файла на FTP, а ваша обработка в 1С уже пытается его скачать, пока он еще не дозаписан до конца.
Это классический и самый надежный способ, проверенный временем. Суть заключается в том, что рядом с основным файлом (например, data.xml) кладется маленький текстовый файл (например, data.xml.md5), содержащий хэш-сумму основного файла.
Рассмотрим алгоритм работы:
Для реализации вычисления хэша в 1С используем объект ХешированиеДанных. Посмотрим на пример кода:
// Пример вычисления хэша MD5 для файла
ХешОбъект = Новый ХешированиеДанных(ХешФункция.MD5);
ХешОбъект.ДобавитьФайл(ПутьКФайлу);
ХешСтрока = НРег(СтрЗаменить(Строка(ХешОбъект.ХешСумма), " ", ""));
Если ХешСтрока = ХешИзФайлаСпутника Тогда
Сообщить("Файл целостен, можно обрабатывать.");
Иначе
Сообщить("Ошибка целостности файла!");
КонецЕсли;
Если мы контролируем и отправку, и получение, то лучшим решением будет использование временных расширений. Проанализируем этот подход подробнее. Отправитель загружает файл под именем document.xml.tmp. Только после того как загрузка на сервер завершена успешно, отправитель выполняет команду переименования в document.xml.
Операция переименования на FTP-сервере является атомарной. Это означает, что если ваша 1С видит в списке файлов document.xml, значит, он гарантированно загружен на сервер полностью. В коде 1С при получении списка файлов через НайтиФайлы() мы просто игнорируем все, что заканчивается на .tmp.
Выясним причину, по которой файл может считаться "битым" с точки зрения бизнес-логики. Если файл имеет формат XML, ZIP или JSON, недокачанный файл просто не пройдет проверку синтаксиса. Разберем по шагам, как это проверить:
ЧтениеZipФайла выдаст ошибку при попытке открытия.ЧтениеXML. Если файл обрывается посередине, закрывающий тег не будет найден, и парсер выдаст исключение.Пример проверки через ZIP:
Попытка
Архив = Новый ЧтениеZipФайла(ПутьКФайлу);
Архив.Закрыть();
// Если ошибок нет, файл скачан полностью
Исключение
Сообщить("Файл поврежден или не докачан.");
КонецПопытки;
Рассмотрим подробнее метод сравнения размеров. Это простой способ, но у него есть подводный камень: некоторые FTP-клиенты и файловые системы резервируют место под файл сразу, и его размер может отображаться как целевой, даже если полезные данные еще не переданы. Тем не менее, для большинства случаев это работает.
Алгоритм действий:
FTPСоединение.НайтиФайлы().Файл.
МассивФайлов = ФТПСоединение.НайтиФайлы(ПутьНаСервере, "data.dat");
Если МассивФайлов.Количество() > 0 Тогда
РазмерНаСервере = МассивФайлов[0].Размер();
ФТПСоединение.Получить(ПутьНаСервере, ЛокальныйПуть);
ЛокальныйФайл = Новый Файл(ЛокальныйПуть);
Если ЛокальныйФайл.Размер() = РазмерНаСервере Тогда
// Успех
КонецЕсли;
КонецЕсли;
Проанализируем ситуацию, когда файл скачивается не самой 1С, а сторонним клиентом. Пока процесс записи в файл активен, операционная система часто блокирует его. Мы можем попытаться открыть файл для записи в монопольном режиме. Если файл "занят" другим процессом, значит, загрузка еще продолжается.
Однако помните, что на Linux-системах это поведение отличается: там файл можно переименовать или удалить, даже если он открыт другим процессом для записи. Поэтому данный метод ориентирован в первую очередь на Windows.
Если техническая возможность позволяет, разберем вариант замены протокола. Начиная с версии платформы 8.3.16, 1С поддерживает работу с SFTP "из коробки". В отличие от старого FTP, SFTP работает через SSH-туннель и имеет встроенные механизмы контроля целостности пакетов. Это значительно снижает вероятность появления "тихо" недокачанных файлов. Использование объекта SFTPСоединение делает обмен данными более надежным и защищенным.
Выясним, как понять, что файл вообще пришел из внешней сети. При скачивании файлов браузерами или продвинутыми клиентами в Windows к файлу добавляется альтернативный поток данных (ADS) под названием Zone.Identifier. В нем прописывается ZoneId=3, что означает "Internet". Хотя стандартное FTPСоединение 1С обычно не ставит такую метку, это может быть полезно для анализа файлов, скачанных внешними утилитами типа curl или wget, запущенными из 1С.
Подводя итог, можно сказать: никогда не полагайтесь на один лишь факт отсутствия ошибки в методе Получить(). Для критически важных данных мы рекомендуем комбинировать методы: использовать временные расширения (.tmp) и обязательно проверять структуру файла (XML/ZIP) или контрольную сумму после завершения загрузки. Это гарантирует, что ваша система не начнет обрабатывать пустые или поврежденные данные, что сохранит целостность информационной базы.