При разработке механизмов интеграции 1С с внешними системами, например, при выгрузке изображений товаров на сайт, разработчики часто сталкиваются с архитектурными сложностями управляемого приложения. Основная проблема заключается в правильном распределении обязанностей между клиентской и серверной частью кода. Разберем по шагам, как эффективно реализовать задачу поиска картинок, их обработки и отправки на FTP-сервер, избегая типичных ошибок проектирования.
Типичная ситуация, описанная в обсуждении: программист выполняет запрос на сервере, получает список номенклатуры и ее изображений, а затем пытается вызвать процедуру выгрузки, которая написана с использованием клиентских методов (например, диалогов выбора файлов или работы с локальными дисками пользователя). Рассмотрим, почему это вызывает затруднения:
FTPСоединение, созданный на клиенте, невозможно передать в качестве параметра на сервер. При попытке такой передачи платформа выдаст ошибку, так как данное соединение является мутабельным объектом, привязанным к конкретному сетевому окружению.ХранилищаЗначения), либо в томах на сервере. Поэтому доступ к ним на сервере получить гораздо проще, чем пытаться пробросить их на клиент.Проанализируем ситуацию и придем к выводу: наиболее правильный и производительный путь — перенести всю логику работы с FTP на сторону сервера, если сервер 1С имеет выход в интернет. Если же доступ к FTP ограничен только рабочим местом пользователя, придется использовать схему с передачей массива данных на клиент.
Если сервер 1С:Предприятия имеет сетевой доступ к FTP-серверу, мы можем реализовать всю логику в одном серверном вызове. Это избавит нас от лишних сетевых пересылок данных между сервером и клиентом.
Рассмотрим алгоритм реализации:
Пример кода серверной процедуры:
&НаСервере
Процедура ВыгрузитьКартинкиНаСервере()
// 1. Получаем данные запросом
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 100
| Номенклатура.Ссылка КАК Номенклатура,
| Номенклатура.Артикул КАК Артикул,
| Номенклатура.ФайлКартинки КАК ФайлКартинки
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.ФайлКартинки <> ЗНАЧЕНИЕ(Справочник.НоменклатураПрисоединенныеФайлы.ПустаяСсылка)";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
// 2. Настраиваем соединение
// Используем пассивный режим для обхода брандмауэров
Соединение = Новый FTPСоединение("ftp.mysite.com", 21, "user", "password", , Истина, 30);
Пока Выборка.Следующий() Цикл
// 3. Получаем двоичные данные файла через БСП
// Это наиболее надежный способ, учитывающий настройки хранения
ДвоичныеДанные = ПрисоединенныеФайлы.ДвоичныеДанныеФайла(Выборка.ФайлКартинки);
Если ТипЗнч(ДвоичныеДанные) <> Тип("ДвоичныеДанные") Тогда
Продолжить;
КонецЕсли;
// 4. Формируем новое имя файла
Расширение = Выборка.ФайлКартинки.Расширение;
ИмяФайлаНаФТП = Выборка.Артикул + "." + Расширение;
// 5. Записываем файл на FTP напрямую из двоичных данных
// Метод Записать позволяет не создавать временных файлов на диске сервера
Попытка
Соединение.Записать(ДвоичныеДанные, ИмяФайлаНаФТП);
// 6. Фиксация результата в доп. реквизите
ОбъектНом = Выборка.Номенклатура.ПолучитьОбъект();
// Пример записи пути (логика зависит от ваших метаданных)
// ОбъектНом.ДополнительныйРеквизитПутьКФото = "http://mysite.com/img/" + ИмяФайлаНаФТП;
ОбъектНом.Записать();
Исключение
ЗаписьЖурналаРегистрации("ВыгрузкаНаFTP", УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка при загрузке артикула " + Выборка.Артикул + ": " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Если доступ к FTP есть только с клиентского компьютера (например, через VPN, поднятый у пользователя), нам придется разделить процесс. Выясним причину, по которой это сложнее: нам нужно передать тяжелые данные (картинки) с сервера на клиент, что может замедлить работу при больших объемах.
Рассмотрим последовательность действий в этом случае:
Шаг 1. На сервере: Собираем массив структур, где в каждой структуре будет содержаться артикул (для имени) и ДвоичныеДанные самого изображения.
Шаг 2. На клиенте: Принимаем этот массив, инициируем FTPСоединение и в цикле выгружаем файлы. При работе на клиенте нам может потребоваться сохранить данные во временный файл перед отправкой, если версия платформы не поддерживает метод Записать для двоичных данных в контексте клиента.
&НаКлиенте
Процедура ЗагрузитьПоОтбору(Команда)
// Получаем данные с сервера
ДанныеДляВыгрузки = ПодготовитьДанныеНаСервере();
Если ДанныеДляВыгрузки.Количество() = 0 Тогда
Сообщить("Нет данных для выгрузки");
Возврат;
КонецЕсли;
// Создаем соединение на клиенте
Соединение = Новый FTPСоединение("ftp.mysite.com", , "login", "pass", , Истина);
Для Каждого Элемент Из ДанныеДляВыгрузки Цикл
// Создаем временное имя для записи на диск клиента
ИмяВременногоФайла = ПолучитьИмяВременногоФайла(Элемент.Расширение);
Элемент.Данные.Записать(ИмяВременногоФайла);
Попытка
Соединение.Записать(ИмяВременногоФайла, Элемент.ИмяНаФТП);
// После успешной записи удаляем временный файл
УдалитьФайлы(ИмяВременногоФайла);
Исключение
Сообщить("Ошибка выгрузки: " + Элемент.Артикул);
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Проанализируем ключевые моменты, которые часто становятся причиной ошибок в коде:
1. Использование навигационных ссылок. Как было замечено в обсуждении, НавигационнаяСсылка (формата e1cib/data/...) не является путем к файлу в операционной системе. Это внутренний адрес объекта в базе 1С. Чтобы получить файл, нужно использовать методы БСП (РаботаСФайлами) или извлекать данные напрямую из реквизита ХранилищеЗначения присоединенного файла.
2. Очистка имен файлов. Артикулы номенклатуры могут содержать символы, недопустимые для имен файлов на сервере (слэши, кавычки, двоеточия). Перед отправкой на FTP обязательно проанализируем строку и заменим спецсимволы на нижнее подчеркивание. Также рекомендуется переводить имена в латиницу во избежание проблем с кодировками на стороне веб-сервера.
3. Пассивный режим FTP. Всегда устанавливайте параметр ПассивныйРежим в значение Истина при создании объекта FTPСоединение. В активном режиме FTP-сервер пытается сам установить обратное соединение с вашим компьютером, что в 99% случаев блокируется корпоративными антивирусами и роутерами.
4. Работа с БСП. Если ваша конфигурация основана на БСП (УТ 11, ERP, КА 2, БП 3), используйте функцию РаботаСФайлами.ДвоичныеДанныеФайла(). Она автоматически определит, где лежит файл — в томе на диске или в базе данных, и вернет вам готовый объект ДвоичныеДанные.
Таким образом, правильная методология заключается в минимизации переключений между клиентом и сервером. Старайтесь выполнять всю работу там, где находятся данные — то есть на сервере. Это обеспечит максимальную скорость обработки и стабильность вашего решения.