# Задание к занятию «Двоичные данные» Результат выполнения первых двух задач вышлите одним файлом (.dt). ## Задача 1. Создать в справочнике «Номенклатура» возможность загрузки и хранения картинки ### Описание задачи Добавить возможность загрузки и хранения картинки в справочнике «Номенклатура». ### Требования к результату Выгрузка информационной базы (.dt) с конфигурацией из предыдущих заданий, в которой реализована возможность загружать и просматривать из формы элемента номенклатуры. Можно выбрать каталог и картинку для загрузки. Номенклатура должна корректно записываться как с выбранной картинкой, так и с пустой картинкой. ### Процесс выполнения 1. Добавим реквизит «ФайлКартинки» с типом «Хранилище значения» в справочнике «Номенклатура». 2. Добавим реквизит «ПутьКартинки» на форму элемента, укажем тип «Строка». В нём будет адрес картинки во временном хранилище. Разместим реквизит на форме с видом «Поле картинки». Установим для элемента формы флажок «Гиперссылка». 3. Добавим на событие Нажатие процедуру «ПутьКартинкиНажатие». 4. Внутри процедуры вызовем асинхронную процедуру для выбора файла с картинкой. Дополнительная процедура нужна, т.к. обработчик элемента формы не может быть асинхронной процедурой: ```bsl &НаКлиенте Процедура ПутьКартинкиНажатие(Элемент, СтандартнаяОбработка) СтандартнаяОбработка = Ложь; ПрочитатьКартинкуНоменклатуры(); КонецПроцедуры ``` Добавим выбор файла с логичными для этого фильтрами отбора формата файла, проверим, что пользователь выбрал файл, и сохраним адрес временного хранилища. ```bsl &НаКлиенте Асинх Процедура ПрочитатьКартинкуНоменклатуры() ПараметрыПомещенияФайла = Новый ПараметрыДиалогаПомещенияФайлов; ПараметрыПомещенияФайла.Фильтр = "Картинка (*.jpg)|*.jpg"; ОписаниеФайла = Ждать ПоместитьФайлНаСерверАсинх(,,, ПараметрыПомещенияФайла, УникальныйИдентификатор); Если ОписаниеФайла = Неопределено Тогда Возврат; КонецЕсли; Если ОписаниеФайла.ПомещениеФайлаОтменено Тогда Возврат; КонецЕсли; ПутьКартинки = ОписаниеФайла.Адрес; КонецПроцедуры ``` 5. Перед записью на сервере запишем в хранилище значений картинку. 6. При чтении на сервере получим картинку из хранилища значений. Пример получения через временное хранилище и записи в реквизит объекта через Хранилище значений: ```bsl &НаСервере Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи) ДвоичныеДанные = ПолучитьИзВременногоХранилища(ПутьКартинки); ТекущийОбъект.ФайлКартинки = Новый ХранилищеЗначения(ДвоичныеДанные); КонецПроцедуры ``` ```bsl &НаСервере Процедура ПриЧтенииНаСервере(ТекущийОбъект) ДвоичныеДанные = ТекущийОбъект.ФайлКартинки.Получить(); ПутьКартинки = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор); КонецПроцедуры ``` ## Задача 2. Сохранение картинки номенклатуры с установленной шириной ### Описание задачи Добавить возможность сохранения в файл картинки номенклатуры с шириной 100 пикселей. ### Требования к результату Выгрузка информационной базы (.dt) с конфигурацией из предыдущих заданий, в которой реализована возможность загружать и просматривать из формы элемента номенклатуры. Ранее выбранную картинку номенклатуры можно сохранить в файл, при этом ширина сохранённой картинки будет 100 пикселей. ### Процесс выполнения 1. Добавим на форму элемента справочника «Номенклатура» команду «СохранитьКартинку», создадим связанную с командой кнопку на коммандной панели формы. 2. Реализуем обработчик команды, в котором вызовем серверный метод для подготовки картинки и предложим пользователю сохранить картинку. ```bsl &НаКлиенте Асинх Процедура СохранитьКартинку(Команда) АдресРезультата = ПодготовитьКартинку(); // Если для номенклатуры не загружена картика, то не будем открывать окно сохранения файла Если Не ЗначениеЗаполнено(АдресРезультата) Тогда Возврат; КонецЕсли; ПараметрыПолученияФайла = Новый ПараметрыДиалогаПолученияФайлов; ПолучитьФайлССервераАсинх(АдресРезультата, Объект.Наименование + ".jpg", ПараметрыПолученияФайла); КонецПроцедуры ``` 3. Реализуем на сервере функцию для подготовки картинки. ```bsl &НаСервере Функция ПодготовитьКартинку() ДвоичныеДанныеИзображения = ПолучитьИзВременногоХранилища(ПутьКартинки); Если ДвоичныеДанныеИзображения = Неопределено Тогда Сообщение = Новый СообщениеПользователю; Сообщение.Текст = "Картинка номенклатуры не загружена"; Сообщение.Сообщить(); Возврат Неопределено; КонецЕсли; Картинка = Новый Картинка(ДвоичныеДанныеИзображения); ОбрабатываемаяКартинка = Новый ОбрабатываемаяКартинка(Картинка); ОбрабатываемаяКартинка.УстановитьРазмер(100, Неопределено); Картинка = ОбрабатываемаяКартинка.ПолучитьКартинку(); ДвоичныеДанныеИзображения = Картинка.ПолучитьДвоичныеДанные(); Возврат ПоместитьВоВременноеХранилище(ДвоичныеДанныеИзображения, УникальныйИдентификатор); КонецФункции ``` ## Задача 3 (со звёздочкой). Разбить файл на части и склеить после этого ### Описание задачи Изучить системные глобальные методы «РазделитьФайл» и «ОбъединитьФайлы». Реализовать аналогичную пару методов самостоятельно во внешней обработке. При реализации не использовать «РазделитьФайл» и «ОбъединитьФайлы», необходимо реализовать их аналоги, пользуясь работой с файлами и потоками. Внешняя обработка должна содержать две закладки: * разделить файл, * объединить файлы. На первой закладке расположено поле «Имя файла», в котором пользователь с помощью стандартного диалога выберет произвольный файл на диске. Также на закладке расположено числовое поле «Размер части» и текстовое поле «Путь», где пользователь с помощью стандартного диалога выбора каталога выберет путь, в котором нужно разместить полученные части файла. На второй закладке должен быть размещён элемент управления «ТаблицаФормы», в котором пользователь сможет указать в нужном ему порядке перечень имён файлов. Также на закладке должен быть размещён элемент «Результат», где пользователь с помощью стандартного диалога сохранения укажет место, в которое нужно сохранить результат склейки. ## Порядок выполнения ### Разбиение файлов * Создать внешнюю обработку с реквизитами: «ИмяФайла», «РазмерЧасти», «Путь», «Результат» и табличной частью «ИменаЧастей» с единственным реквизитом «ИмяЧасти». * В обработке создать форму и разместить в ней две страницы: «Разделить файл» и «Объединить файлы». На странице «Разделить файл» разместить реквизиты «Имя файла» и «Размер части». * В элементе управления «ИмяФайла» и «Путь» включить отображение кнопки выбора «КнопкаВыбора = Да». * Реализовать алгоритм выбора файла с помощью стандартного диалога в поле «ИмяФайла» в обработчике «НачалоВыбора». * Повторить для элемента управления «Путь», но использовать диалог в режиме выбора каталога. * Создать команду «РазделитьФайл» и разместить её на форме на закладке «Разделить файл». * Написать алгоритм разбиения файла на части. Каждая часть сохраняется в отдельный файл. ### Подсказка по алгоритму разбиения * Выяснить размер исходного файла и записать в переменную «ОсталосьПрочитать». См. объект «Файл» и «ФайловыйПоток». * В цикле открыть новый файловый поток для записи. Имя части сгенерировать как `"Часть_"+"Счетчик`. * Записать в файловый поток части методом `ИсходныйПоток.КопироватьВ(ПотокЧасти, РазмерЧасти)`. * Перед записью проконтролировать, что `РазмерЧасти` меньше переменной `ОсталосьПрочитать`. Если РазмерЧасти больше — скопировать только оставшееся число байт * Уменьшить переменную «ОсталосьПрочитать» на «РазмерЧасти». ### Объединение файлов * На закладке «Объединение файлов» разместить табличную часть «ИменаЧастей» и поле реквизита «Результат». * В поле реквизита «Результат» включить отображение кнопки выбора и написать алгоритм выбора пути файла. * Создать команду «Объединить файлы» и разместить её на форме. * Написать обработчик команды таким образом, чтобы он создал файл с именем, указанным в поле «Результат» и перенёс в него содержимое всех файлов, перечисленных в таблице «ИменаЧастей». ### Подсказка по алгоритму объединения * Открыть для записи поток в файл из поля «Результат». * В цикле по таблице `ИменаЧастей` открывать потоки для чтения текущей строки таблицы и копировать их в поток-результат методом `ПотокИсточник.КопироватьВ`. * Количество байт контролировать в этом случае не надо. ### Подсказка: [результат выполнения домашнего задания](Examples/homework-5-9-example.md).