Как пакетно изменить расширения картинок в базе 1С после конвертации на диске?

Программист 1С v8.3 (Управляемые формы) 1С:Управление нашей фирмой Управленческий учет Торговля и дистрибуция
← На главную

В работе с информационной системой 1С часто возникает необходимость оптимизации хранения больших объемов данных, таких как изображения. Представьте ситуацию: вы загрузили в базу данных 1С порядка 800 изображений в формате PNG, каждое размером около 1 МБ. Это неизбежно привело к значительному увеличению размера базы, что негативно сказалось на ее производительности и скорости работы. Стандартным и эффективным решением в таких случаях является перенос файлов из самой базы на дисковое хранилище (так называемые «тома»), а также оптимизация формата изображений для уменьшения их размера.

В данном материале мы рассмотрим комплексный подход к решению этой проблемы: от оптимизации хранения до пакетного обновления данных в самой 1С после внешней конвертации файлов.

Анализ проблемы и предложенное решение

Исходная проблема заключалась в том, что большое количество PNG-файлов (около 800 штук), размещенных непосредственно в базе 1С, существенно замедлило ее работу. Первым шагом к решению стало правильное стратегическое решение: базу перенесли в SQL, а сами файлы отделили от базы на дисковое хранилище. Это первый и очень важный шаг, так как он предотвращает рост размера информационной базы за счет бинарных данных и улучшает общую производительность.

Однако даже при хранении файлов на диске, формат PNG для фотографий, особенно больших, не является оптимальным с точки зрения объема. PNG лучше подходит для изображений с прозрачностью, логотипов или графики с четкими границами, тогда как JPG обеспечивает гораздо лучшую степень сжатия для фотографий, хоть и является форматом с потерями. Поэтому возникла идея:

  1. Выгрузить все файлы картинок на диск ПК, сохраняя структуру папок.
  2. Пакетно сконвертировать их из формата PNG в JPG с помощью сторонних инструментов.
  3. Разместить сконвертированные файлы обратно на дисковом хранилище, заменяя исходные PNG-файлы на JPG по тем же путям.
  4. Обновить записи о файлах в базе 1С, чтобы система знала о новом расширении и пути.

Последний пункт — самый критичный и является предметом нашего детального рассмотрения: как пакетно переписать записи о файлах в 1С, изменив расширение с .png на .jpg?

Структура хранения присоединенных файлов в 1С

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

Этот справочник содержит несколько ключевых реквизитов, которые критически важны для управления файлами:

  1. Расширение: В этом реквизите хранится расширение файла (например, "png", "jpg").
  2. ПутьКФайлу: Это реквизит хранит относительный путь к файлу в томе хранения. Важно отметить, что этот путь часто включает в себя и само имя файла вместе с расширением. Например, это может выглядеть как "20210813\IMG_7739.jpg".
  3. Том: Этот реквизит содержит ссылку на элемент справочника "Тома хранения файлов", который указывает на физическую папку на сервере, где хранятся файлы.

Мы должны понимать, что изменение расширения файла на диске и изменение его записи в базе — это две разные, но взаимосвязанные операции. После того как мы физически заменим файлы на диске, нам обязательно нужно обновить записи в 1С, чтобы система корректно отображала и обращалась к новым файлам.

Почему внешняя конвертация и хранение в томах — это оптимальный путь?

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

  1. Оптимизация размера базы данных:

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

  2. Производительность доступа к файлам:

    Когда файлы хранятся в томах на диске, 1С не тратит ресурсы на чтение и запись больших бинарных данных непосредственно из/в СУБД. Вместо этого система обращается к файловой системе сервера, что зачастую быстрее и эффективнее, особенно для большого количества файлов или файлов значительного размера. Это улучшает производительность доступа к файлам, их загрузки и отображения.

  3. Эффективность формата JPG:

    Использование формата PNG для фотографий большого размера значительно увеличивает объем данных по сравнению с JPG. PNG является форматом без потерь, что идеально для изображений с прозрачностью или четкими границами, но избыточно для большинства фотографий. JPG, являясь форматом с потерями, обеспечивает гораздо лучшую степень сжатия для фотографий при сохранении приемлемого качества. Конвертация PNG в JPG, как предложено в теме, является очень эффективным способом уменьшения общего размера хранилища и, как следствие, положительно сказывается на скорости работы с файлами. При конвертации мы можем регулировать степень сжатия, чтобы найти оптимальный баланс между размером файла и качеством изображения.

  4. Ограничения встроенных средств 1С:

    Платформа 1С действительно имеет объект Картинка и метод Преобразовать для работы с изображениями. Однако этот метод, согласно некоторым источникам, может быть ограничен конвертацией в определенные форматы (например, только в BMP и PNG), а не из PNG в JPG для всех версий платформы. Это делает внешнюю пакетную конвертацию с помощью специализированных инструментов (таких как IrfanView или онлайн-конвертеры) более надежным и универсальным решением для массовой обработки изображений.

  5. Настройка томов хранения файлов:

    Для корректной работы с файлами, хранящимися на диске, мы должны предварительно настроить тома хранения файлов в 1С. Это специальные папки на сервере, в которых физически будут лежать файлы. В настройках программы 1С можно установить флажок "Хранить файлы в томах на диске" и определить сами тома. Важно отметить, что путь уже созданному тому нельзя изменить, и том нельзя удалить, пока на него ссылаются файлы. Также возможно настроить правила размещения файлов в томах в зависимости от их вида или свойств.

Пошаговое решение: Обновление записей в 1С

Теперь, когда мы полностью понимаем контекст и преимущества выбранного подхода, перейдем к основной задаче — обновлению записей в базе 1С. Предполагается, что вы уже выполнили следующие шаги:

  1. Выгрузили все PNG-файлы на диск.
  2. Пакетно сконвертировали их в JPG-файлы с помощью внешнего ПО.
  3. Разместили сконвертированные JPG-файлы обратно на дисковом хранилище (в томах), точно по тем же путям и с теми же именами (за исключением расширения), что и исходные PNG-файлы.

Теперь нам нужно, чтобы 1С "узнала" о новых расширениях. Для этого мы создадим внешнюю обработку, которая будет выполнять пакетное изменение реквизитов Расширение и ПутьКФайлу в справочнике НоменклатураПрисоединенныеФайлы.

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


&НаСервереБезКонтекста
Процедура КомандаВыполнитьНаСервере(РасширениеИсходное,РасширениеКонечное)

    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
    | НоменклатураПрисоединенныеФайлы.Ссылка КАК Ссылка
    |ИЗ
    | Справочник.НоменклатураПрисоединенныеФайлы КАК НоменклатураПрисоединенныеФайлы
    |ГДЕ
    | НоменклатураПрисоединенныеФайлы.Расширение = &РасширениеИсходное
    | //И НоменклатураПрисоединенныеФайлы.ТипХраненияФайла = ЗНАЧЕНИЕ(Перечисление.ТипыХраненияФайлов.ВТомахНаДиске)";

    Запрос.УстановитьПараметр("РасширениеИсходное", РасширениеИсходное);

    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();

    ДлинаИсходногоРасширения = СтрДлина(РасширениеИсходное);

    Пока Выборка.Следующий Цикл
        Попытка
            СпрОбъект = Выборка.Ссылка.ПолучитьОбъект();
            СпрОбъект.Расширение = РасширениеКонечное;
            СпрОбъект.ПутьКФайлу = Лев(СпрОбъект.ПутьКФайлу,СтрДлина(СпрОбъект.ПутьКФайлу) - ДлинаИсходногоРасширения) + РасширениеКонечное;
            СпрОбъект.Записать();
        Исключение
            // Тут надо обработать ошибку. Например, вывести сообщение в Журнал регистрации.
            // Сообщить("Ошибка при обработке файла " + Выборка.Ссылка.Наименование + ": " + ОписаниеОшибки());
        КонецПопытки;
    КонецЦикла;

КонецПроцедуры

&НаКлиенте
Процедура КомандаВыполнить(Команда)

    РасширениеИсходное = "png";
    РасширениеКонечное = "jpg";

    КомандаВыполнитьНаСервере(РасширениеИсходное,РасширениеКонечное);

КонецПроцедуры

Давайте разберем этот код по частям, чтобы полностью понять его логику и функциональность:

  1. Процедура КомандаВыполнитьНаСервере(РасширениеИсходное, РасширениеКонечное):

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

    • Инициализация запроса: Мы создаем новый объект Запрос. С его помощью мы будем выбирать все записи из справочника НоменклатураПрисоединенныеФайлы, которые соответствуют нашему условию.

      
      Запрос = Новый Запрос;
      Запрос.Текст = "ВЫБРАТЬ
      | НоменклатураПрисоединенныеФайлы.Ссылка КАК Ссылка
      |ИЗ
      | Справочник.НоменклатураПрисоединенныеФайлы КАК НоменклатураПрисоединенныеФайлы
      |ГДЕ
      | НоменклатураПрисоединенныеФайлы.Расширение = &РасширениеИсходное
      | //И НоменклатураПрисоединенныеФайлы.ТипХраненияФайла = ЗНАЧЕНИЕ(Перечисление.ТипыХраненияФайлов.ВТомахНаДиске)";
      

      В тексте запроса мы выбираем Ссылка на элементы справочника НоменклатураПрисоединенныеФайлы. Условие ГДЕ НоменклатураПрисоединенныеФайлы.Расширение = &РасширениеИсходное позволяет нам отфильтровать только те файлы, у которых текущее расширение совпадает с исходным (в нашем случае "png").

      Обратите внимание на закомментированную строку //И НоменклатураПрисоединенныеФайлы.ТипХраненияФайла = ЗНАЧЕНИЕ(Перечисление.ТипыХраненияФайлов.ВТомахНаДиске). Если вы абсолютно уверены, что все обрабатываемые файлы хранятся в томах на диске (что рекомендуется), и вы хотите ограничить выборку только ими, вы можете раскомментировать эту строку. Однако, если у вас в базе присутствуют файлы, хранящиеся непосредственно в информационной базе (что менее оптимально для больших файлов), и вы также хотите их обработать, то эту строку следует оставить закомментированной.

    • Установка параметров и выполнение запроса:

      
      Запрос.УстановитьПараметр("РасширениеИсходное", РасширениеИсходное);
      РезультатЗапроса = Запрос.Выполнить();
      Выборка = РезультатЗапроса.Выбрать();
      

      Здесь мы присваиваем значение параметру &РасширениеИсходное (например, "png") и выполняем запрос. Полученный результат запроса затем преобразуется в объект Выборка, по которому мы будем итерироваться.

    • Расчет длины исходного расширения:

      ДлинаИсходногоРасширения = СтрДлина(РасширениеИсходное);

      Эта переменная нам понадобится для корректного обновления реквизита ПутьКФайлу, чтобы "отрезать" старое расширение.

    • Цикл по результатам запроса:

      
      Пока Выборка.Следующий Цикл
          //...
      КонецЦикла;
      

      Мы используем цикл Пока Выборка.Следующий Цикл для последовательного перебора всех найденных ссылок на присоединенные файлы.

    • Получение объекта и изменение реквизитов:

      
      Попытка
          СпрОбъект = Выборка.Ссылка.ПолучитьОбъект();
          СпрОбъект.Расширение = РасширениеКонечное;
          СпрОбъект.ПутьКФайлу = Лев(СпрОбъект.ПутьКФайлу,СтрДлина(СпрОбъект.ПутьКФайлу) - ДлинаИсходногоРасширения) + РасширениеКонечное;
          СпрОбъект.Записать();
      Исключение
          // Обработка ошибок
      КонецПопытки;
      

      Внутри цикла для каждой ссылки мы выполняем следующее:

      • СпрОбъект = Выборка.Ссылка.ПолучитьОбъект();: Мы получаем объект справочника. Важно: работа с объектами (ПолучитьОбъект, изменение реквизитов, Записать) обеспечивает соблюдение всех механизмов записи 1С, включая вызов событий и проверку данных. Для 800 файлов это приемлемый и безопасный подход, хотя для миллионов записей можно рассмотреть более низкоуровневые прямые изменения регистров сведений, что, однако, требует большей осторожности.
      • СпрОбъект.Расширение = РасширениеКонечное;: Мы устанавливаем новое расширение для файла (например, "jpg") в соответствующем реквизите.
      • СпрОбъект.ПутьКФайлу = Лев(СпрОбъект.ПутьКФайлу,СтрДлина(СпрОбъект.ПутьКФайлу) - ДлинаИсходногоРасширения) + РасширениеКонечное;: Это ключевая строка для обновления пути. Мы используем функцию Лев(), чтобы "отрезать" от текущего значения ПутьКФайлу старое расширение, а затем конкатенируем (склеиваем) оставшуюся часть пути с новым расширением. Например, если ПутьКФайлу был "20210813\IMG_7739.png" и исходное расширение "png" (длиной 3 символа), то мы получим "20210813\IMG_7739" и добавим к нему "jpg", в результате чего путь станет "20210813\IMG_7739.jpg". Это критически важно, так как поле ПутьКФайлу также содержит расширение.
      • СпрОбъект.Записать();: Мы сохраняем все изменения в базе данных.
      • Обработка ошибок: Блок Попытка...Исключение очень важен. Он позволяет продолжить выполнение обработки даже в случае возникновения ошибки при записи какого-либо конкретного файла. Мы рекомендуем добавить в блок Исключение вывод подробного сообщения об ошибке в Журнал регистрации 1С или в отдельное окно, чтобы можно было проанализировать, с какими файлами возникли проблемы.
  2. Процедура КомандаВыполнить(Команда):

    Эта клиентская процедура отвечает за запуск серверной части. Она будет доступна пользователю в форме обработки.

    
    &НаКлиенте
    Процедура КомандаВыполнить(Команда)
    
        РасширениеИсходное = "png";
        РасширениеКонечное = "jpg";
    
        КомандаВыполнитьНаСервере(РасширениеИсходное,РасширениеКонечное);
    
    КонецПроцедуры
    

    Здесь мы жестко задаем исходное расширение как "png" и конечное как "jpg". Затем просто вызываем серверную процедуру КомандаВыполнитьНаСервере, передавая ей эти параметры. При необходимости, можно вынести эти параметры на форму обработки в виде полей ввода, чтобы пользователь мог гибко задавать расширения для конвертации.

Рекомендации и важные моменты

Перед тем как применять подобное решение на практике, особенно на рабочей базе, мы настоятельно рекомендуем принять во внимание следующие важные моменты:

  1. Тестирование на тестовой базе:

    КРИТИЧЕСКИ ВАЖНО всегда сначала выполнять подобные операции на **тестовой базе**, которая является точной копией вашей рабочей базы. Это позволит убедиться в корректности работы обработки, проверить все сценарии и исключить любые непредвиденные последствия без риска для основной работы предприятия.

  2. Резервное копирование:

    Перед началом любых манипуляций с данными на **рабочей базе** обязательно сделайте **полную и актуальную резервную копию** информационной базы 1С. Также не забудьте создать резервную копию самих томов с файлами на диске. Это ваша "подушка безопасности" на случай непредвиденных проблем.

  3. Имена файлов и их расположение:

    Убедитесь, что после внешней конвертации имена файлов (без расширения) и их расположение в томах на диске **не изменились**. Если файлы будут перемещены или переименованы (помимо изменения расширения), 1С не сможет найти их по обновленным путям, даже если записи в базе будут исправлены. Строгая привязка "один к одному" между старым PNG и новым JPG по местоположению и имени (до расширения) обязательна.

  4. Степень сжатия JPG:

    При конвертации из PNG в JPG вы можете регулировать степень сжатия. Экспериментируйте с различными настройками, чтобы найти оптимальный баланс между размером файла и приемлемым качеством изображения. Чрезмерное сжатие может привести к заметной потере качества, особенно на детальных изображениях.

  5. Права доступа:

    Пользователь, под которым будет запускаться данная обработка, должен иметь достаточные права доступа для чтения и изменения данных в справочнике НоменклатураПрисоединенныеФайлы. В противном случае, обработка завершится с ошибкой прав доступа.

  6. Отображение картинок в списках:

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

  7. Общая оптимизация работы с большими базами:

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

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

← На главную