Приветствую.

Задача - разместить фото сотрудника в элементе справочника.

На форме есть булев реквизит "Сохранять фото в базе".

В чем проблема - если фото изначально было сохранено не в базе а где то на диске, и теперь пользователь просто ставит галочку "Сохранять фото в базе", то при повторном открытии фотка исчезает.
Что я делаю не так ? Код привожу ниже.

Для галочки "сохранять в базе" поставил "изменяет данные", форма становится модифицированной. Однако не помогло.

```1c
    &НаКлиенте
    Процедура ВыбратьКартинку(Команда)
    НачатьПомещениеФайла(Новый ОписаниеОповещения("ВыбратьКартинкуЗавершение", ЭтотОбъект),,,ИСТИНА,УникальныйИдентификатор);
    КонецПроцедуры

    &НаКлиенте
    Процедура ВыбратьКартинкуЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
    Если Результат Тогда
    ПутьККартинке = ВыбранноеИмяФайла;
    Картинка = Адрес;
    Модифицированность = ИСТИНА;
    КонецЕсли;

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

    &НаСервере
    Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    Если СохранятьФотоВБазе И ЭтоАдресВременногоХранилища(Картинка) Тогда
    ТекущийОбъект.ХранилищеКартинки = Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(Картинка));
    ТекущийОбъект.ПутьКФайлу = ";
    Иначе
    ТекущийОбъект.ПутьКФайлу = ПутьККартинке;
    ТекущийОбъект.ХранилищеКартинки = ";
    КонецЕсли;
    КонецПроцедуры

    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если ЗначениеЗаполнено(Объект.ПутьКФайлу) Тогда
    Картинка = ПоместитьВоВременноеХранилище(Новый Картинка(Объект.ПутьКФайлу));
    Иначе
    СохранятьФотоВБазе = ИСТИНА;
    Картинка = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "ХранилищеКартинки");
    КонецЕсли;

    КонецПроцедуры
```
---
Все. Сделал.

Вот что получилось в итоге:

```1c
    &НаКлиенте
    Процедура ВыбратьФотографию(Команда)
    НачатьПомещениеФайла(Новый ОписаниеОповещения("ВыбратьФотографиюЗавершение", ЭтотОбъект),,,ИСТИНА,УникальныйИдентификатор);
    КонецПроцедуры

    &НаКлиенте
    Процедура ВыбратьФотографиюЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
    Если Результат Тогда
    Картинка = Адрес;
    Файл = Новый Файл(ВыбранноеИмяФайла);
    Объект.Расширение = Файл.Расширение;
    Модифицированность = ИСТИНА;
    КонецЕсли;

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

    Процедура СохранитьВБазе(ИзменилосьМестоХранения, АдресВременный, Отказ)
    ДвоичныеДанные = Неопределено;

    Если ЭтоАдресВременногоХранилища(АдресВременный) Тогда
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременный);
    КонецЕсли;

    Если ИзменилосьМестоХранения Тогда
    ПутьКФайлу = Константы.КаталогХраненияФотографий.Получить() + Объект.Ссылка.УникальныйИдентификатор() + Объект.Ссылка.Расширение;
    Файл = Новый Файл(ПутьКФайлу);
    Если НЕ Файл.Существует() Тогда
    Отказ = ИСТИНА;
    Сообщить("Файл недоступен");
    Возврат;
    КонецЕсли;
    Если ДвоичныеДанные = Неопределено Тогда
    ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу);
    КонецЕсли;

    УдалитьФайлы(ПутьКФайлу);

    КонецЕсли;

    Если ДвоичныеДанные <> Неопределено Тогда
    СохранениеФото = РегистрыСведений.ФотографииСотрудников.СоздатьМенеджерЗаписи();
    СохранениеФото.Сотрудник = Объект.Ссылка;
    СохранениеФото.Фото = Новый ХранилищеЗначения(ДвоичныеДанные);
    СохранениеФото.Записать();

    КонецЕсли;

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

    Процедура СохранитьНаСервере(ИзменилосьМестоХранения, АдресВременный, Отказ)
    ДвоичныеДанные = Неопределено;
    Если ЭтоАдресВременногоХранилища(АдресВременный) Тогда
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременный);
    КонецЕсли;

    Если ИзменилосьМестоХранения Тогда
    СохранениеФото = РегистрыСведений.ФотографииСотрудников.СоздатьМенеджерЗаписи();
    СохранениеФото.Сотрудник = Объект.Ссылка;
    Если ДвоичныеДанные = Неопределено Тогда
    СохранениеФото.Прочитать();
    ДвоичныеДанные = СохранениеФото.Фото.Получить();
    КонецЕсли;
    СохранениеФото.Удалить();

    КонецЕсли;

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

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

    &НаСервере
    Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    ИзменилосьМестоХранения = ?(ТекущийОбъект.Ссылка<>Справочники.ФизическиеЛица.ПустаяСсылка() И ТекущийОбъект.МестоХраненияФайла<>Объект.Ссылка.МестоХраненияФайла, ИСТИНА, ЛОЖЬ);
    Если ТекущийОбъект.МестоХраненияФайла = Перечисления.МестоХраненияФайла.ВБазе Тогда
    СохранитьВБазе(ИзменилосьМестоХранения, Картинка, Отказ);
    Иначе
    СохранитьНаСервере(ИзменилосьМестоХранения, Картинка, Отказ);
    КонецЕсли;

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

    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Объект.Ссылка <> Справочники.ФизическиеЛица.ПустаяСсылка() Тогда
    Если Объект.МестоХраненияФайла = Перечисления.МестоХраненияФайла.ВБазе Тогда
    ЗначениеКлюча = Новый Структура;
    ЗначениеКлюча.Вставить("Сотрудник", Объект.Ссылка);

    КлючЗаписи = РегистрыСведений.ФотографииСотрудников.СоздатьКлючЗаписи(ЗначениеКлюча);

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

    КонецЕсли;

    КонецЕсли;

    КонецПроцедуры
```
---
Процедура ВыбратьКартинкуЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
ВыбранноеИмяФайла это просто имя файла без пути.
Соответственно последующее открытие и "Картинка = ПоместитьВоВременноеХранилище(Новый Картинка(Объект.ПутьКФайлу));"
Объект.ПутьКФайлу содержить просто имя файла без пути.
---
нет, это путь к файлу. Проверял отладчиком. Этот код не работает только если ранее не сохраненный в базе файл.
---
в Веб-клиенте это может не быть путь к файлу.
---
я подключаюсь в тонком клиенте. Если ошибка при помещении в хранилище, тогда почему все работает через ВыбратьКартинку ? И в последующем считывании такого элемента отображение тоже в норме.
---
я к тому, что этот код не будет работать ожидаемо в веб-клиенте.
Ошибка пропадания картинки в тонком клиенте возможно в том коде, который мы не видим.
На изменение реквизита формы "СохранятьФотоВБазе" обработчик указан? Может там что меняется.
---
обработчика там нет. Просто поставлена галочка "Сохраняемые данные" дабы при изменении состояния флажка форма становилось модифицированной.
---
проверьте что содержится в Картинка.

```1c
    Если СохранятьФотоВБазе И ЭтоАдресВременногоХранилища(Картинка) Тогда
```

Картинка будет проходить проверку на ЭтоАдресВременногоХранилища, но в нем (временном хранилище) будет Неопределено.
Как вариант, проверять ПутьККартинке.
---
Как в картинке будет Неопределено, если эта самая картинка сейчас на форме и ее видно нормально ?
---
не в картинке будет Неопределено, в во временном хранилище.
ПоместитьВоВременноеХранилище(Новый Картинка(Объект.ПутьКФайлу)) помещает двоичные данные. Но хранится они будут до первого же последующего серверного вызова.
Если не указан второй параметр :
"Если параметр не указан, помещенное значение будет удалено после очередного запроса сервера из общего модуля, при контекстном и неконтекстном серверном вызове из формы, при серверном вызове из модуля команды или при получении формы. "
---
В данном случае вот решение проблемы:

```1c
    Картинка = ПоместитьВоВременноеХранилище(Новый Картинка(Объект.ПутьКФайлу),УникальныйИдентификатор);
```

Но далее возникает другая проблема. Когда пользователь снимает флаг сохранения в базе. Картинка пропадет.
---
Тогда придется писать обработчик для СохранятьФотоВБазе. Только вот как сделать обратный процесс - картинку из формы сохранить на диск ? Пока вот, сижу читаю синтаксис-помощник.
---
могу подбросить идеи. Как это делается в типовых.
1. картинки в базе не желательно хранить в самом справочнике. Лучше использовать отдельный справочник "СотрудникиПрисоединенныеФайлы" или регистрСведений
2. всю логику по хранению и получению картинки реализовать в отдельном общем модуле.
3. Хранить файлы не с путями клиентских компьютеров, в в отдельной папке "На Сервере".
4. Имена файлов не обязательно такие же, как и загружаемые. Генерировать свои уникальные имена. Сохранять их в реквизит.
5. При выборе хранения в базе загружать ДД в реквизит хранилище данных. При наличии файла на сервере - удалять этот файл.
6. При выборе хранения в файлах, выгружать из хранилища и записывать в файлы, как указано выше.

Рассмотреть возможность внедрения БСП(если ее еще нет в конфигурации) и использовать подсистему РаботаСФайлами.
---
Буду делать регистр сведений.
---
В ЗУП 3.1(или скорее всего в БСП в целом) фотографии сотрудников это как раз регистр сведений, можешь взять за основу
---
Все. Сделал.

Вот что получилось в итоге:

```1c
    &НаКлиенте
    Процедура ВыбратьФотографию(Команда)
    НачатьПомещениеФайла(Новый ОписаниеОповещения("ВыбратьФотографиюЗавершение", ЭтотОбъект),,,ИСТИНА,УникальныйИдентификатор);
    КонецПроцедуры

    &НаКлиенте
    Процедура ВыбратьФотографиюЗавершение(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
    Если Результат Тогда
    Картинка = Адрес;
    Файл = Новый Файл(ВыбранноеИмяФайла);
    Объект.Расширение = Файл.Расширение;
    Модифицированность = ИСТИНА;
    КонецЕсли;

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

    Процедура СохранитьВБазе(ИзменилосьМестоХранения, АдресВременный, Отказ)
    ДвоичныеДанные = Неопределено;

    Если ЭтоАдресВременногоХранилища(АдресВременный) Тогда
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременный);
    КонецЕсли;

    Если ИзменилосьМестоХранения Тогда
    ПутьКФайлу = Константы.КаталогХраненияФотографий.Получить() + Объект.Ссылка.УникальныйИдентификатор() + Объект.Ссылка.Расширение;
    Файл = Новый Файл(ПутьКФайлу);
    Если НЕ Файл.Существует() Тогда
    Отказ = ИСТИНА;
    Сообщить("Файл недоступен");
    Возврат;
    КонецЕсли;
    Если ДвоичныеДанные = Неопределено Тогда
    ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу);
    КонецЕсли;

    УдалитьФайлы(ПутьКФайлу);

    КонецЕсли;

    Если ДвоичныеДанные <> Неопределено Тогда
    СохранениеФото = РегистрыСведений.ФотографииСотрудников.СоздатьМенеджерЗаписи();
    СохранениеФото.Сотрудник = Объект.Ссылка;
    СохранениеФото.Фото = Новый ХранилищеЗначения(ДвоичныеДанные);
    СохранениеФото.Записать();

    КонецЕсли;

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

    Процедура СохранитьНаСервере(ИзменилосьМестоХранения, АдресВременный, Отказ)
    ДвоичныеДанные = Неопределено;
    Если ЭтоАдресВременногоХранилища(АдресВременный) Тогда
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВременный);
    КонецЕсли;

    Если ИзменилосьМестоХранения Тогда
    СохранениеФото = РегистрыСведений.ФотографииСотрудников.СоздатьМенеджерЗаписи();
    СохранениеФото.Сотрудник = Объект.Ссылка;
    Если ДвоичныеДанные = Неопределено Тогда
    СохранениеФото.Прочитать();
    ДвоичныеДанные = СохранениеФото.Фото.Получить();
    КонецЕсли;
    СохранениеФото.Удалить();

    КонецЕсли;

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

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

    &НаСервере
    Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    ИзменилосьМестоХранения = ?(ТекущийОбъект.Ссылка<>Справочники.ФизическиеЛица.ПустаяСсылка() И ТекущийОбъект.МестоХраненияФайла<>Объект.Ссылка.МестоХраненияФайла, ИСТИНА, ЛОЖЬ);
    Если ТекущийОбъект.МестоХраненияФайла = Перечисления.МестоХраненияФайла.ВБазе Тогда
    СохранитьВБазе(ИзменилосьМестоХранения, Картинка, Отказ);
    Иначе
    СохранитьНаСервере(ИзменилосьМестоХранения, Картинка, Отказ);
    КонецЕсли;

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

    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Объект.Ссылка <> Справочники.ФизическиеЛица.ПустаяСсылка() Тогда
    Если Объект.МестоХраненияФайла = Перечисления.МестоХраненияФайла.ВБазе Тогда
    ЗначениеКлюча = Новый Структура;
    ЗначениеКлюча.Вставить("Сотрудник", Объект.Ссылка);

    КлючЗаписи = РегистрыСведений.ФотографииСотрудников.СоздатьКлючЗаписи(ЗначениеКлюча);

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

    КонецЕсли;

    КонецЕсли;

    КонецПроцедуры
```
---
Файл картинки тип ХранилищеЗначений. Поле на форме АдресКартинки тип "Поле HTML документа":

```1c
    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    НаборЗаписей = РегистрыСведений.РасчетныеЛисткиBonus.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.ФизЛицо.Установить( запись.ИсходныйКлючЗаписи.ФизЛицо);
    НаборЗаписей.Отбор.Период.Установить( Запись.ИсходныйКлючЗаписи.Период) ;
    НаборЗаписей.Прочитать();
    Если НаборЗаписей.Количество() > 0 Тогда
    ДанныеФайла = НаборЗаписей[0].ФайлКартинки.Получить();
    КонецЕсли;
    КонецПроцедуры

    &НаКлиенте
    Процедура ПриОткрытии(Отказ)
    Если ТипЗнч(ДанныеФайла) = тип("ДвоичныеДанные") Тогда
    ИмяФайла = ПолучитьИмяВременногоФайла("htm");
    ДанныеФайла.Записать(ИмяФайла);
    АдресКартинки = ИмяФайла ;
    КонецЕсли;
    КонецПроцедуры
```