Как сохранить фотографию контрагента из 1С в папку на диске?

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

При разработке внешних обработок и интеграционных механизмов часто возникает задача пакетного или одиночного сохранения присоединенных файлов (например, фотографий контрагентов, сканов документов или карточек) из базы 1С в заданную папку на жестком диске. Разберем различные способы решения этой задачи в зависимости от архитектуры хранения файлов в конфигурации.

Проанализируем структуру хранения данных. В большинстве конфигураций на платформе 1С:Предприятие 8.3 для работы с изображениями и документами используется подсистема работы с файлами. При этом физически двоичные данные могут находиться либо непосредственно в таблицах базы данных (в реквизите с типом ХранилищеЗначения), либо во внешних томах на диске.

Способ 1. Получение данных через структуру подсистемы работы с файлами

Рассмотрим штатный механизм, используемый в конфигурациях с БСП или аналогичными библиотеками работы с файлами. При вызове серверной функции РаботаСФайламиВызовСервера.ПолучитьДанныеФайлаДляСохранения() формируется структура параметров файла, содержащая адрес во временном хранилище и метаинформацию о файле (имя, расширение).

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


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

Способ 2. Прямое чтение из реквизита «ХранилищеЗначения» на сервере

Посмотрим на ситуацию, когда требуется выполнить пакетную выгрузку фотографий в фоновом режиме или в рамках серверной процедуры без использования клиентских контекстов и промежуточных временных хранилищ. Если данные хранятся в самой информационной базе, мы можем напрямую обратиться к реквизиту ФайлХранилище объекта файла или его версии.

Разберем пример серверного кода для чтения двоичных данных из справочника:


&НаСервере
Процедура СохранитьФотоКонтрагентаНаСервере(СсылкаНаКонтрагента, КаталогВыгрузки)
    
    // Проверяем заполненность ссылки на файл картинки
    Если НЕ ЗначениеЗаполнено(СсылкаНаКонтрагента.ФайлКартинки) Тогда
        Возврат;
    КонецЕсли;
    
    ОбъектФайла = СсылкаНаКонтрагента.ФайлКартинки;
    
    // В зависимости от структуры метаданных хранилище может находиться в самом файле или в справочнике версий
    Хранилище = Неопределено;
    Расширение = "png";
    
    // Вариант 1: прямое хранение в реквизите файла
    Если ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(ОбъектФайла, "ФайлХранилище") Тогда
        Хранилище = ОбъектФайла.ФайлХранилище;
    // Вариант 2: хранение через реквизит ТекущаяВерсия
    ИначеЕсли ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(ОбъектФайла, "ТекущаяВерсия") 
        И ЗначениеЗаполнено(ОбъектФайла.ТекущаяВерсия) Тогда
        Хранилище = ОбъектФайла.ТекущаяВерсия.ФайлХранилище;
        Расширение = ОбъектФайла.ТекущаяВерсия.Расширение;
    КонецЕсли;
    
    Если Хранилище <> Неопределено Тогда
        ДвоичныеДанные = Хранилище.Получить();
        
        Если ТипЗнч(ДвоичныеДанные) = Тип("ДвоичныеДанные") Тогда
            
            // Очищаем наименование от запрещенных символов файловой системы
            ИмяБезСпецСимволов = СсылкаНаКонтрагента.Наименование;
            ЗапрещенныеСимволы = "\/:*?""<>|";
            Для Сч = 1 По СтрДлина(ЗапрещенныеСимволы) Цикл
                Символ = Сред(ЗапрещенныеСимволы, Сч, 1);
                ИмяБезСпецСимволов = СтрЗаменить(ИмяБезСпецСимволов, Символ, "_");
            КонецЦикла;
            
            ИмяФайла = ИмяБезСпецСимволов + "." + Расширение;
            ПолныйПутьКФайлу = КаталогВыгрузки + "\" + ИмяФайла;
            
            ДвоичныеДанные.Записать(ПолныйПутьКФайлу);
            
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Способ 3. Выгрузка при хранении файлов в томах на диске

Выясним причину, по которой метод Хранилище.Получить() может возвращать Неопределено. Это происходит в тех случаях, когда в базе включено хранение файлов в томах на диске. В этой ситуации бинарное содержимое не дублируется в таблицах базы данных, а реквизит ФайлХранилище остается пустым.

Для сохранения файла из тома выполним следующие действия:

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

// Пример извлечения файла, хранящегося в томе
ИсходныйПуть = ОбъектФайла.Том.ПолныйПутьWindows + ОбъектФайла.ПутьКФайлу;
ЦелевойПуть = КаталогВыгрузки + "\" + Контрагент.Наименование + "." + ОбъектФайла.Расширение;

Если НайтиФайлы(ИсходныйПуть).Количество() > 0 Тогда
    КопироватьФайл(ИсходныйПуть, ЦелевойПуть);
КонецЕсли;

Важные особенности и рекомендации по реализации

Рассмотрим ключевые нюансы, на которые следует обратить внимание при разработке обработки:

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