Разберем частую и довольно неприятную ситуацию: необходимо сформировать прайс-лист в формате Excel, в который выводятся изображения товаров. Если в базе хранится множество качественных фотографий (например, по 1,5 МБ каждая для выгрузки на сайт), итоговый файл Excel может раздуться до 200 и более мегабайт. Ситуация усложняется, если база работает на Linux-сервере, а формирование происходит в фоновом регламентном задании, что исключает использование стандартных Windows-компонент.
Проанализируем несколько способов, как мы можем элегантно решить эту задачу, оптимизировать вес изображений и не уронить производительность сервера.
Посмотрим на базовый метод, который работает на стороне сервера без привлечения сторонних утилит. Мы можем программно уменьшить масштаб картинки перед тем, как поместить ее в макет табличного документа.
Важный момент: если применять масштабирование ко всем картинкам подряд, мы можем сильно испортить небольшие изображения. Поэтому перед ресайзом проверим вес исходного файла. Для этого используем метод РазмерФайла(). Рассмотрим код, который реализует эту логику:
ДанныеФайла = РаботаСФайламиСлужебныйВызовСервера.ДанныеФайла(Выборка.ОсновноеИзображение);
АдресФотографии = ДанныеФайла.СсылкаНаДвоичныеДанныеФайла;
Данные = ПолучитьИзВременногоХранилища(АдресФотографии);
Картинка = Новый Картинка(Данные);
// Проверяем размер файла (например, если больше 300 КБ)
Если Картинка.РазмерФайла() > 300000 Тогда
ОбрабатываемаяКартинка = Новый ОбрабатываемаяКартинка(Картинка);
// Уменьшаем масштаб до 50% (коэффициент подбирается опытным путем)
ОбрабатываемаяКартинка.Масштабировать(50);
МаленькаяКартинка = ОбрабатываемаяКартинка.ПолучитьКартинку();
ОблСтроки.Рисунки.Фото.Картинка = МаленькаяКартинка;
Иначе
ОблСтроки.Рисунки.Фото.Картинка = Картинка;
КонецЕсли;
ОблСтроки.Рисунки.Фото.РазмерКартинки = РазмерКартинки.АвтоРазмер;
Если ваша платформа обновлена до версий 8.3.23 и выше, мы можем использовать более современный подход. Платформа получила встроенный объект ПреобразованиеКартинки. Он работает быстрее старого механизма и использует современные алгоритмы сжатия.
Этот объект позволяет не просто изменить размер, но и поменять формат «на лету». Очень часто вес генерируют изображения в формате PNG (формат без потерь). Конвертация из тяжелого PNG в оптимизированный JPEG с заданным качеством может уменьшить вес файла в 5–10 раз. При записи объекта Картинка мы можем явно указать формат ФорматКартинки.JPEG.
Также вместо веса в байтах логичнее проверять ширину картинки в пикселях. У объекта Картинка есть свойства Ширина() и Высота(). Проанализируем этот подход: если ширина картинки превышает 800px, уменьшаем её до 800px пропорционально. Это гарантирует четкость в ячейке Excel без избыточного веса.
Рассмотрим еще один отличный инструмент, появившийся в платформе 8.3.22. При экспорте табличного документа в различные форматы появилась возможность управлять качеством картинок глобально.
У объекта ТабличныйДокумент теперь есть свойство ПлотностьСохраняемыхКартинок. Оно принимает значения из системного перечисления ПлотностьВыводаКартинок (например, Плотность72dpi, Плотность96dpi). Для экранного прайс-листа в Excel качества 72 или 96 dpi будет более чем достаточно.
Установив это свойство перед записью документа в файл, мы укажем платформе 1С автоматически «облегчить» все встроенные изображения при выгрузке, что избавит нас от необходимости обрабатывать каждую фотографию в цикле.
Если встроенных средств недостаточно, на Linux серверах стандартом де-факто для работы с изображениями является пакет ImageMagick (консольная утилита convert). Однако у нас есть ограничение: файлы картинок лежат в базе (в хранилище), а напрямую сохранять их на диск во временные папки не всегда удобно из-за прав доступа на сервере.
Выясним, как это обойти. Мы можем использовать стандартные потоки ввода-вывода (stdin/stdout). В 1С (начиная с 8.3.18) существует объект ЗапускПроцесса. Он позволяет передать двоичные данные картинки напрямую в консольную утилиту и получить результат обратно в переменную 1С, полностью минуя файловую систему.
В завершение разберем несколько важных моментов, которые обязательно нужно учитывать при массовой обработке тяжелых файлов:
Неопределено сразу после вывода области в макет.ТипФайлаТабличногоДокумента.XLSX. В отличие от старого XLS, формат XLSX представляет собой zip-архив, который гораздо лучше сжимает встроенные медиафайлы и нативно поддерживается алгоритмами платформы.Используя комбинацию этих методов — проверку размеров перед обработкой, программное сжатие в JPEG и настройку плотности вывода — мы сможем генерировать компактные и красивые прайс-листы даже из самых «тяжелых» баз данных.