Загрузка данных


#Область ПрограммныйИнтерфейс

// Функция выполняет действие:
//   Записать Файлы Из Формы Предпросмотра
//
// Параметры:
//     Таб - Произвольный 
//     СсылкаНаДокумент - Произвольный
Процедура ЗаписатьФайлыИзФормыПредпросмотра(Таб, СсылкаНаДокумент) Экспорт
	
	// Определим, есть ли файлы к записи
	ЕстьФайлыНовые = ЛОЖЬ;
	Для Каждого Строка Из Таб Цикл
		
		Если Строка.ЭтоНовыйФайл Тогда
			
			ЕстьФайлыНовые = Истина;
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;
	
	Если Не ЕстьФайлыНовые Тогда
		
		Возврат;
		
	КонецЕсли;
	
	СтруктураСпособаХранения = ПолучитьСпособХранения();
	
	Если СтруктураСпособаХранения = Неопределено Тогда
		
		МассивКУдалению = Новый Массив;
		// Уберем все прикрепленные в предпросмотре файлы
		Для Каждого Строка Из Таб Цикл
			
			Если Строка.ЭтоНовыйФайл Тогда
				
				Если ЭтоАдресВременногоХранилища(Строка.Путь) Тогда
					
					УдалитьИзВременногоХранилища(Строка.Путь);
					
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЦикла;
		
		Для Каждого Строка Из МассивКУдалению Цикл
			
			Таб.Удалить(Строка);
			
		КонецЦикла;
		
	КонецЕсли;
	
	Набор = РегистрыСведений.ПрикрепленныеФайлы.СоздатьНаборЗаписей();
	Набор.Отбор.ИспользуемыйДокумент.Установить( СсылкаНаДокумент );
	
	ТекДата = ЧасовыеПоясаСервер.ТекущееВремяИБ();
	
	Для Каждого Строка Из Таб Цикл
		
		Если Строка.ЭтоНовыйФайл Тогда
			
			НоваяЗапись = Набор.Добавить();
			
			ЗаполнитьСтрокуИМенеджерЗаписиИзФормыПредпросмотра(НоваяЗапись, Строка, СтруктураСпособаХранения, СсылкаНаДокумент, ТекДата);
			
		КонецЕсли;
		
	КонецЦикла;
	
	Набор.Записать( ЛОЖЬ );
	
КонецПроцедуры


// Процедура выполняет действие:
//   Получить Массив Структур Файлов Документа
//
// Параметры:
//     Документ - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьМассивСтруктурФайловДокумента(Документ) Экспорт
	
	МассивРезультат = Новый Массив;
	
	ТипДокумента = Метаданные.НайтиПоТипу(ТипЗнч(Документ)).Имя;
	Запрос = Новый Запрос;
	Запрос.Текст = 
		" ВЫБРАТЬ 
		|	ПрикрепленныеФайлы.UUID,
		|	ПрикрепленныеФайлы.Название
		| ИЗ 
		|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
		| ГДЕ
		|	Выразить(ПрикрепленныеФайлы.ИспользуемыйДокумент КАК  %2.%1)= &Документ";
	
	Если ТипЗнч(Документ) = Тип("СправочникСсылка.ШаблоныСообщений") Тогда
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "%2", "Справочник");
	Иначе
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "%2", "Документ");
	КонецЕсли;
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "%1", ТипДокумента);
	Запрос.УстановитьПараметр("Документ", Документ);
	
	РезультатЗапроса = Запрос.Выполнить();
	
	ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
	
	Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
		
		МассивРезультат.Добавить(Новый Структура("ИмяФайла,ИдФайла",ВыборкаДетальныеЗаписи.Название, ВыборкаДетальныеЗаписи.UUID));
		
	КонецЦикла;
	
	Возврат МассивРезультат;
	
КонецФункции


// Процедура выполняет действие:
//   Получить Количество Файлов Документа
//
// Параметры:
//     СсылкаНаДокумент - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьКоличествоФайловДокумента(СсылкаНаДокумент)Экспорт
	
	ИмяТипа = Метаданные.НайтиПоТипу(ТипЗнч(СсылкаНаДокумент)).Имя;
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		" ВЫБРАТЬ 
		|	КОЛИЧЕСТВО(ПрикрепленныеФайлы.UUID) КАК  UUID
		| ИЗ 
		|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
		| ГДЕ 
		|	Выразить(ПрикрепленныеФайлы.ИспользуемыйДокумент КАК  Документ.%1) = &Документ";
		
		
	Запрос.УстановитьПараметр("Документ", СсылкаНаДокумент);
	Запрос.Текст = СтрЗаменить(Запрос.Текст, "%1", ИмяТипа);
	РезультатЗапроса = Запрос.Выполнить();
	
	ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
	
	Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
		Возврат ВыборкаДетальныеЗаписи.UUID;
	КонецЦикла;
	
	Возврат 0;
	
КонецФункции


// Процедура выполняет действие:
//   Записать Файлы По Списку Помеченных
//
// Параметры:
//     УникальныйИдентификатор - Произвольный 
//     СписокПрикрепленныхФайлов - Произвольный 
//     СсылкаНаДокумент - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция ЗаписатьФайлыПоСпискуПомеченных(УникальныйИдентификатор, СписокПрикрепленныхФайлов, СсылкаНаДокумент)Экспорт
	
	тзПрикрепленныеФайлы = Новый ТаблицаЗначений;
	
	тзПрикрепленныеФайлы.Колонки.Добавить("UUID");
	тзПрикрепленныеФайлы.Колонки.Добавить("Дата");
	тзПрикрепленныеФайлы.Колонки.Добавить("Название");
	тзПрикрепленныеФайлы.Колонки.Добавить("Описание");
	тзПрикрепленныеФайлы.Колонки.Добавить("СпособХранения");
	тзПрикрепленныеФайлы.Колонки.Добавить("ПометкаУдаления");
	тзПрикрепленныеФайлы.Колонки.Добавить("ТипФайла");
	тзПрикрепленныеФайлы.Колонки.Добавить("Путь");
	
	ТекДата = ЧасовыеПоясаСервер.ТекущееВремяИБ();
	
	Кол = 0;
	
	Для Каждого ЭлСписка Из СписокПрикрепленныхФайлов Цикл
		
		Если ЭлСписка.Пометка Тогда
			
			Кол = Кол + 1;
			
			НСТр = ТЗПрикрепленныеФайлы.Добавить();
			ЗаполнитьЗначенияСвойств(НСТр,ЭлСписка.Значение,,"UUID");
			Нстр.Дата = ТекДата;
			
			Если Нстр.СпособХранения = ПредопределенноеЗначение("Перечисление.СпособХраненияФайла.УдаленнаяДиректория") 
				ИЛИ Нстр.СпособХранения = ПредопределенноеЗначение("Перечисление.СпособХраненияФайла.ИнформационнаяБаза") Тогда
				
				Нстр.Путь = ИТ_ОбщиеФункцииФормДокументовСервер
						.ПолучитьПутьДоФайлаИзУдаленнойДиректорииНаСервере(
							ЭлСписка.Значение.UUID,
							НСтр.Название, 
							ЭлСписка.Значение.Хранилище,
							УникальныйИдентификатор,
							Нстр.СпособХранения);
			КонецЕсли;
			
			Если Нстр.Путь = Неопределено Тогда 
				ТЗПрикрепленныеФайлы.Удалить(Нстр);
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЦикла;
	
	пфЗаписатьПрикрепленныеФайлы(СсылкаНаДокумент , тзПрикрепленныеФайлы,,ЛОЖЬ);	
	
	Возврат Кол;
    
	
КонецФункции


// Процедура выполняет действие:
//   Получить Массив Структур Для Списка Идентификаторов
//
// Параметры:
//     СсылкаНаДокумент - Произвольный
//
// Возвращаемое значение:
//    Произвольный
функция ПолучитьМассивСтруктурДляСпискаИдентификаторов(СсылкаНаДокумент) Экспорт
	
	Таблица = ДобавитьПолеКартинкиВТаблицуФайлов(ПрикрепленныеФайлыСервер.пфПолучитьСписокПрикрепленныхФайлов(СсылкаНаДокумент));
	
	Массив = Новый Массив;
	
	Для Каждого Строка Из Таблица Цикл
		
		Стр = Новый Структура("UUID, Название, Картинка");
		ЗаполнитьЗначенияСвойств( Стр  , Строка);
		Массив.Добавить(Стр);
		
	КонецЦикла;
	
	Возврат Массив;
	
КонецФункции


// Составляет полное имя файла из имени каталога и имени файла.
// 
// ИмяКаталога  – Строка, содержащая путь к каталогу файла на диске.
// ИмяФайла     – Строка, содержащая имя файла, без имени каталога.
// :
// Строка – полное имя файла с учетом каталога.
//
// Параметры:
//     ИмяКаталога - Произвольный 
//     ИмяФайла - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьИмяФайла(ИмяКаталога, ИмяФайла) Экспорт

	Если Не ПустаяСтрока(ИмяФайла) Тогда
		
		Возврат ИмяКаталога + ?(Прав(ИмяКаталога, 1) = "\", "", "\") + ИмяФайла;	
		
	Иначе
		
		Возврат ИмяКаталога;
		
	КонецЕсли;

КонецФункции  // ПолучитьИмяФайла()


// Формирует имя каталога для сохранения/чтения файлов. Для различных типов объектов возможны 
// различные алгоритмы определения каталога.
// 
// ОбъектФайла  – Ссылка на объект данных, для которого прикрепляются файлы.
// :
// Строка – каталог файлов для указанного объекта и пользователя.
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьИмяКаталога() Экспорт

	// Получим рабочий каталог из свойств пользователя.
	// РабочийКаталог = ПолучитьЗначениеПоУмолчанию(ПараметрыСеанса.ТекущийПользователь, "ОсновнойКаталогФайлов");
	РабочийКаталог = "";

	// Если рабочий каталог не указан получим каталог временных файлов прогаммы
	Если ПустаяСтрока(РабочийКаталог) Тогда
		РабочийКаталог = КаталогВременныхФайлов();
	КонецЕсли;

	// Так как при различных указаниях рабочего каталога возможно наличие или отсутствие
	// последнего слеша, приведем строку каталога к унифицированному виду - без слеша на конце.
	Если Прав(РабочийКаталог, 1) = "\" Тогда
		РабочийКаталог = Лев(РабочийКаталог, СтрДлина(РабочийКаталог) - 1);
	КонецЕсли;

	Возврат РабочийКаталог;

КонецФункции  // ПолучитьИмяКаталога()


// ////////////////////////////////////////////////////////////////////////////////
// Модуль описывает работу системы с прикрепленными файлами
// Функция проверки существования указанной директории
// :
// - Директория
// 
// - Структура с кодом ошибки.
//
// Параметры:
//     Директория - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция пфПроверитьДиректорию(Директория)  Экспорт
	
	КодОшибки = Новый Структура("КодОшибки");
	
	ВыбКаталог = Новый Файл(Директория);
	
	// Проверяем существует ли выбранный каталог
	Если Не ВыбКаталог.Существует() Тогда
		КодОшибки.КодОшибки = "Выбранный каталог недоступен с сервера 1С:Предприятия.";
	ИначеЕсли Не ВыбКаталог.ЭтоКаталог() Тогда 
		КодОшибки.КодОшибки = "Каталог не существует (выбранный путь указывает на файл).";
	КонецЕсли;
	
	Возврат КодОшибки;
	
КонецФункции


// Функция заполняющая и инициализирующая таблицу значений для документа
// Передаваемое значение:
// - Документ - ссылка на документ, для которого требуется получить список файлов
// - Таблица, параметр указывающий дополнительную табличную часть
// :
// Структура описывающая таблицу данных отображающая файлы
//
// Параметры:
//     Документ - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция пфПолучитьСписокПрикрепленныхФайлов(Документ) Экспорт
	
	Если Не ЗначениеЗаполнено(Документ) Тогда
		// Возвращаем только файловую структуру
		
		тзПрикрепленныеФайлы = Новый ТаблицаЗначений;
		
		тзПрикрепленныеФайлы.Колонки.Добавить("UUID");
		тзПрикрепленныеФайлы.Колонки.Добавить("Дата");
		тзПрикрепленныеФайлы.Колонки.Добавить("Название");
		тзПрикрепленныеФайлы.Колонки.Добавить("Описание");
		тзПрикрепленныеФайлы.Колонки.Добавить("СпособХранения");
		тзПрикрепленныеФайлы.Колонки.Добавить("ПометкаУдаления");
		тзПрикрепленныеФайлы.Колонки.Добавить("ТипФайла");
		тзПрикрепленныеФайлы.Колонки.Добавить("Путь");
		
	Иначе  // Если ЗначениеНеЗаполнено(Документ) Тогда ... 
		
		// Формируем запрос, получающий значение по регистратору
		ЗапросСсылкаНаДокумент= "";
		
		Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Документ)) Тогда
		
			ЗапросСсылкаНаДокумент = " ПрикрепленныеФайлы.ИспользуемыйДокумент ССЫЛКА Справочник." + Документ.Метаданные().Имя + "  И  ";
		
		
		ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Документ)) Тогда
		
			ЗапросСсылкаНаДокумент = " ПрикрепленныеФайлы.ИспользуемыйДокумент ССЫЛКА Документ." + Документ.Метаданные().Имя+ "  И  ";
		
		
		КонецЕсли; 
		
		
		Запрос = Новый Запрос;
		Запрос.УстановитьПараметр("Ссылка", Документ);
		
		
		Запрос.Текст =
		" ВЫБРАТЬ   РАЗРЕШЕННЫЕ  
		|	ПрикрепленныеФайлы.UUID,
		|	ПрикрепленныеФайлы.Название,
		|	ПрикрепленныеФайлы.Описание,
		|	ПрикрепленныеФайлы.ТипФайла КАК  ТипФайла,
		|	ПрикрепленныеФайлы.ДатаИзменения КАК  Дата,
		|	ПрикрепленныеФайлы.СпособХранения,
// |	ПрикрепленныеФайлы.ПутьДоФайла КАК  Путь, не открывать, в противном случае прикрепеление файлов  ПО  почте  НЕ  работ
// ает
		|	 ЛОЖЬ  КАК  ПометкаУдаления
		| ИЗ 
		|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
		| ГДЕ 
		|	"+ ЗапросСсылкаНаДокумент + " ПрикрепленныеФайлы.ИспользуемыйДокумент = &Ссылка" ;
		
		
		тзПрикрепленныеФайлы = Запрос.Выполнить().Выгрузить();
		
		// Добавляем дополнительные колонки
		тзПрикрепленныеФайлы.Колонки.Добавить("Путь");
		тзПрикрепленныеФайлы.Колонки.Добавить("Отметка");
		
	КонецЕсли;  // Если ЗначениеНеЗаполнено(Документ) Тогда ... Иначе ...
	
	Возврат тзПрикрепленныеФайлы;
	
КонецФункции


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


// Процедура выполняет действие:
//   Записать Файлы По Списку Отмеченных
//
// Параметры:
//     Результат - Произвольный 
//     СсылкаНаДокумент - Произвольный 
//     СписокФайловДляВыбора - Произвольный 
//     УИ - Произвольный 
//     Решение - Произвольный 
//     Очищать - Произвольный
//
// Возвращаемое значение:
//    Произвольный
функция ЗаписатьФайлыПоСпискуОтмеченных(Результат, СсылкаНаДокумент, СписокФайловДляВыбора, УИ, Решение, Очищать = Истина) Экспорт
	
	тзПрикрепленныеФайлы = Новый ТаблицаЗначений;
	тзПрикрепленныеФайлы.Колонки.Добавить("Дата");
	тзПрикрепленныеФайлы.Колонки.Добавить("Название");
	тзПрикрепленныеФайлы.Колонки.Добавить("Описание");
	тзПрикрепленныеФайлы.Колонки.Добавить("ТипФайла");
	тзПрикрепленныеФайлы.Колонки.Добавить("UUID");
	тзПрикрепленныеФайлы.Колонки.Добавить("СпособХранения");
	тзПрикрепленныеФайлы.Колонки.Добавить("ПометкаУдаления");
	тзПрикрепленныеФайлы.Колонки.Добавить("Путь");
	тзПрикрепленныеФайлы.Колонки.Добавить("Картинка");
	
	Для Каждого ФайлИзСписка Из СписокФайловДляВыбора Цикл
		
		Если ФайлИзСписка.Пометка Тогда
			
			НС = тзПрикрепленныеФайлы.Добавить();
			НС.Дата = ЧасовыеПоясаСервер.ТекущееВремяИБ();
			
			ЗаполнитьЗначенияСвойств(НС, Результат.Получить(ФайлИзСписка.Значение));
			НС.UUID = ФайлИзСписка.Значение; 	
			Если НС.СпособХранения <> Неопределено Тогда
				Если НС.СпособХранения = ПредопределенноеЗначение("Перечисление.СпособХраненияФайла.ИнформационнаяБаза") Тогда
					НС.Картинка = БиблиотекаКартинок.ВложениеХранилище;
					НС.Путь = ИТ_ОбщиеФункцииФормДокументовСервер.ПолучитьПутьДоФайлаИзУдаленнойДиректорииНаСервере(ФайлИзСписка.Значение,
					НС.Название,
					Неопределено,
					УИ,
					НС.СпособХранения,
					Решение);
				ИначеЕсли НС.СпособХранения = ПредопределенноеЗначение("Перечисление.СпособХраненияФайла.УдаленнаяДиректория") Тогда
					НС.Картинка = БиблиотекаКартинок.ВложениеУдаленное;
					НС.Путь = ИТ_ОбщиеФункцииФормДокументовСервер.ПолучитьПутьДоФайлаИзУдаленнойДиректорииНаСервере(ФайлИзСписка.Значение,
					НС.Название,
					Неопределено,
					УИ,
					НС.СпособХранения);
				ИначеЕсли НС.СпособХранения = ПредопределенноеЗначение("Перечисление.СпособХраненияФайла.ПроизвольнаяДиректория") Тогда
					НС.Картинка = БиблиотекаКартинок.ВложениеВнешнее;
				КонецЕсли;
			КонецЕсли;
			
		КонецЕсли;
	КонецЦикла;
	
	пфЗаписатьПрикрепленныеФайлы(СсылкаНаДокумент , тзПрикрепленныеФайлы,,Очищать);
	
	Возврат тзПрикрепленныеФайлы.Количество();
	
КонецФункции

// Процедура записи табличной части файлов
// :
// Документ - документ, к которому прикрепляются файлы
// ТаблицаЗначений - Таблица, для которой записываются файлы
// Таблица			- Дополнительная таблица, используемая для хранения файлов в разных разрезах
// Запись файлов делиться на три этапа:
// 1. Поиск изменений
// 2. Удаление удаленных файлов
// 3. Добавление новых файлов
//
// Параметры:
//     Документ - Произвольный 
//     ТаблицаЗначений - Произвольный 
//     ТекущийПользователь - Произвольный 
//     Очищать - Произвольный 
//     ЭлектронноеПисьмо - Произвольный
//     МассивUUIDФайлов - Произвольный
//	   ПерезаписыватьУжеСуществующие - Булево	
Процедура пфЗаписатьПрикрепленныеФайлы(Документ, ТаблицаЗначений, 
					ТекущийПользователь = Неопределено, 
					Очищать = Истина, 
					ЭлектронноеПисьмо = Неопределено,
					МассивUUIDФайлов = Неопределено,
					ПерезаписыватьУжеСуществующие = Истина) Экспорт 

	// Создаем набор записей
	НаборЗаписей = РегистрыСведений.ПрикрепленныеФайлы.СоздатьНаборЗаписей();
	
	// Текущий пользователь
	Если Не ЗначениеЗаполнено(ТекущийПользователь) Тогда
		ТекущийПользователь = ИТ_ГлобальныйМодульСервер.ИТ_глЗначениеПеременной("глТекущийПользователь");
	КонецЕсли;
	
	ТекДата			    = ТекущаяДата();
	
	// Читаем набор записей из базы, для указанного документа
	НаборЗаписей.Отбор.ИспользуемыйДокумент.Установить(Документ);
	НаборЗаписей.Прочитать();
	
	Инд = НаборЗаписей.Количество() - 1;
	
	// ЭтоНовый = Ложь;
	// 
	// Если Инд<0 Тогда
	// ЭтоНовый = Истина;
	// КонецЕсли;
	
	Изменено = Ложь;
	
	// Перебираем элементы коллекции
	Пока Инд >= 0 И ПерезаписыватьУжеСуществующие Цикл
		
		Запись = НаборЗаписей.Получить(Инд);
		
		// Ищем запись в таблице значений
		СтрокаТаблицы = ТаблицаЗначений.Найти(Запись.UUID, "UUID");
		
		// Если запись не найдена, тогда удаляем запись
		Если СтрокаТаблицы = Неопределено Тогда
			
			// УДАЛЕНИЕ ЗАПИСИ
			// 
			
			Если Очищать Тогда
				
				// Удаляем файл, только в том случае, если тип записи был в удаленную директорию
				Если Запись.СпособХранения = Перечисления.СпособХраненияФайла.УдаленнаяДиректория Тогда
					Попытка
						УдалитьФайлы(ПолучитьУдаленнуюДиректорию(), ПолучитьСкрытоеНазвание(Запись.Название, Запись.UUID));
					Исключение
						ИТ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОписаниеОшибки());
					КонецПопытки;
				КонецЕсли;
				
				НаборЗаписей.Удалить(Инд);
				
				Изменено = Истина;
				
			КонецЕсли;

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

				Изменено = Истина;
			
			КонецЕсли;  // Если Не ЗначениеНеЗаполнено(СтрокаТаблицы.Путь) Тогда 
			
			// Проверяем изменилось ли описание
			Если Запись.Описание <> СтрокаТаблицы.Описание Тогда
				Запись.Описание = СтрокаТаблицы.Описание;
				Изменено = Истина;
			КонецЕсли;
			
			Если Запись.ТипФайла <> СтрокаТаблицы.ТипФайла Тогда
				Запись.ТипФайла = СтрокаТаблицы.ТипФайла;
				Изменено = Истина;
			КонецЕсли;
			
			// Проверяем изменилось ли название
			Если Запись.Название <> СтрокаТаблицы.Название Тогда
				Запись.Название = СтрокаТаблицы.Название;
				Изменено = Истина;
			КонецЕсли;
			
		КонецЕсли;  // Если СтрокаТаблицы = Неопределено Тогда ... Иначе ...
		
		
		// Переходим к следующей записи
		Инд = Инд -1;
		
	КонецЦикла;
	
	
	// Если были изменения, тогда их записываем
	Если Изменено Тогда
		НаборЗаписей.Записать();
		НаборЗаписей.Отбор.ИспользуемыйДокумент.Установить(Документ);
	КонецЕсли;
	
	Если Очищать Тогда
		
		НаборЗаписей.Очистить();
		
	КонецЕсли;
	

	// ДОБАВЛЕНИЕ НОВЫХ ФАЙЛОВ
	// 
	
	// Выбираем из таблицы ТОЛЬКО новые значения
	Изменено = Ложь;
	
	МассивUUIDФайлов = Новый Массив;
	
	Для Каждого Файл Из ТаблицаЗначений Цикл
		
		// Предварительно сохраним в текстовый файл аттач
		Если ТипЗнч(Файл.Путь) = Тип("ИнтернетПочтовоеСообщение") Тогда
			СохранитьВложенныеПисьма(Документ, 
						ТекущийПользователь, 
						ТекДата, 
						НаборЗаписей, 
						Файл.Путь, 
						ЭлектронноеПисьмо);
			
			Изменено = Истина;
		Иначе
			// Если добавляется новый файл, тогда
			
			Если ЗначениеЗаполнено(Файл.UUID) И ЗначениеЗаполнено(Файл.Название) И ПерезаписыватьУжеСуществующие Тогда
				
				Запрос = Новый Запрос;
				Запрос.Текст = 
				" ВЫБРАТЬ   РАЗРЕШЕННЫЕ  
				|	ПрикрепленныеФайлы.ИспользуемыйДокумент КАК Документ,
				|	ПрикрепленныеФайлы.UUID,
				|	ПрикрепленныеФайлы.СпособХранения
				| ИЗ 
				|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
				| ГДЕ 
				|	ПрикрепленныеФайлы.ИспользуемыйДокумент = &Документ
				|	 И  ПрикрепленныеФайлы.UUID = &UUID";
				
				Запрос.УстановитьПараметр("UUID", Файл.UUID);
				Запрос.УстановитьПараметр("Документ", Документ);
				
				Результат = Запрос.Выполнить();
				
				Если Результат.Пустой() Тогда
					ЗаписатьФайл(Документ, ТекущийПользователь, ТекДата, НаборЗаписей, Файл, ЭлектронноеПисьмо);
				
					Изменено = Истина;
				КонецЕсли
			КонецЕсли;
			Если Не ЗначениеЗаполнено(Файл.UUID)  И ЗначениеЗаполнено(Файл.Название) Тогда
				НовыйUUID = Неопределено;
				
				ЗаписатьФайл(Документ, ТекущийПользователь, ТекДата, НаборЗаписей, Файл, ЭлектронноеПисьмо, НовыйUUID);
				
				Файл.UUID = НовыйUUID;
				Изменено = Истина;
			КонецЕсли;  // Если ЗначениеНеЗаполнено(Файл.UUID) Тогда ...
			
			МассивUUIDФайлов.Добавить(Файл.UUID);
			
		КонецЕсли;
		
		                                                           
	КонецЦикла;  // Для Каждого Файл Из ТаблицаЗначений Цикл ...
	
	// Если были изменения, тогда их записываем
	Если Изменено Тогда
		Попытка
			Если Очищать Тогда
				НаборЗаписей.Записать(ЛОЖЬ);
			Иначе
				НаборЗаписей.Записать(Истина);
			КонецЕсли;
		Исключение
			ИТ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОписаниеОшибки());
		КонецПопытки;
	КонецЕсли;
	
	НаборЗаписей.Очистить();
	
КонецПроцедуры


// Функция получения пустой структуры хранения файла
//
// Параметры:
//     UUID - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция пфПолучитьСтруктуруЗаписи(UUID = Неопределено) Экспорт 
	
	// Создаем структуру 
	Результат = Новый Структура;
	Результат.Вставить("КодОшибки", "");
	
	Результат.Вставить("UUID");
	Результат.Вставить("Дата");
	Результат.Вставить("Название");
	Результат.Вставить("Описание");
	Результат.Вставить("ТипФайла");
	Результат.Вставить("СпособХранения");
	Результат.Вставить("ПометкаУдаления");
	Результат.Вставить("Путь");
	
	
	Если Не ЗначениеЗаполнено(UUID) Тогда 
		
		Результат.ПометкаУдаления = Ложь;
		Результат.UUID = "";
		
	Иначе
		Запрос = Новый Запрос;
		
		Запрос.Текст = 
		" ВЫБРАТЬ   РАЗРЕШЕННЫЕ  
		|	ПрикрепленныеФайлы.UUID,
		|	ПрикрепленныеФайлы.ДатаСоздания КАК  Дата,
		|	ПрикрепленныеФайлы.ТипФайла,
		|	ПрикрепленныеФайлы.Описание,
		|	ПрикрепленныеФайлы.ПутьДоФайла КАК  Путь,
		|	ПрикрепленныеФайлы.СпособХранения,
		|	ПрикрепленныеФайлы.Название
		| ИЗ 
		|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
		| ГДЕ 
		|	ПрикрепленныеФайлы.UUID = &UUID";
		
		Запрос.УстановитьПараметр("UUID", UUID);
		
		Выборка = Запрос.Выполнить().Выбрать();
		
		Если Выборка.Следующий() Тогда
			Результат.UUID 				= Выборка.UUID;
			Результат.Дата 				= Выборка.Дата;
			Результат.Название 			= Выборка.Название;
			Результат.Описание			= Выборка.Описание;
			Результат.ТипФайла 			= Выборка.ТипФайла;
			Результат.СпособХранения 	= Выборка.СпособХранения;
			Результат.Путь 				= "";
			Результат.ПометкаУдаления 	= Ложь;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции


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

	Возврат СтруктураЗаписи.UUID;
	
КонецФункции


// Функция генерирования UUID
//
// Возвращаемое значение:
//    Произвольный
Функция пфПолучитьUUID() Экспорт 
	Возврат ПолучитьUUID();
КонецФункции


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


// /////////////////////////////////////////////////////////////////////
// ЛОКАЛЬНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ
//
// Параметры:
//     ТаблицаЗначений - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция  ДополнитьТаблицаДаннымиПриКопированиДокументов(ТаблицаЗначений) Экспорт
	

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


// Процедура выполняет действие:
//     Получить Структуру Данных Файла
//
// Параметры:
//     УИД - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция  ПолучитьСтруктуруДанныхФайла(УИД) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		" ВЫБРАТЬ   РАЗРЕШЕННЫЕ  
		|	ПрикрепленныеФайлы.ИспользуемыйДокумент КАК Документ,
		|	ПрикрепленныеФайлы.UUID,
		|	ПрикрепленныеФайлы.СпособХранения,
		|	ПрикрепленныеФайлы.Автор,
		|	ПрикрепленныеФайлы.ДатаИзменения,
		|	ПрикрепленныеФайлы.ДатаСоздания,
		|	ПрикрепленныеФайлы.Название,
		|	ПрикрепленныеФайлы.Описание,
		|	ПрикрепленныеФайлы.Редактор,
		|	ПрикрепленныеФайлы.Хранилище,
		|	ПрикрепленныеФайлы.ПутьДоФайла,
		|	ПрикрепленныеФайлы.ТипФайла
		| ИЗ 
		|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
		| ГДЕ 
		|	ПрикрепленныеФайлы.UUID = &UUID";

	Запрос.УстановитьПараметр("UUID", УИД);

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

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

	Структура = Новый Структура;	
	
	Если ВыборкаДетальныеЗаписи.Следующий() Тогда
		
		Для ш = 0 по Результат.Колонки.Количество() - 1 Цикл;
			Структура.Вставить(Результат.Колонки[ш].Имя, ВыборкаДетальныеЗаписи[Результат.Колонки[ш].Имя] );
		КонецЦикла;
	
	КонецЕсли;
	
	Возврат Структура;
	
КонецФункции  // ПолучитьСтруктуруДанныхФайла


// Функция генерирования UUID
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьUUID() Экспорт
	UUID = Новый УникальныйИдентификатор;
	Возврат Строка(UUID);
	
КонецФункции


// Функция получения названия файла из его имени и UUID
//
// Параметры:
//  Название		 - Строка
//  UUID			 - Строка
//  ШифрованноеИмя	 - Строка 
// 
// Возвращаемое значение:
//  Строка 
//
Функция ПолучитьСкрытоеНазвание(Название, UUID, ШифрованноеИмя = "", ЭтоКартинкаВходящейПочты = Ложь, СоздаватьКаталог = Истина) Экспорт
	
	сокрUUID = UUID;
	
	Если ШифрованноеИмя = "" Тогда
		ПредставлениеИмени = "";
		Шифрованное = ПолучитьШифрованноеИмя(Название, сокрUUID, ПредставлениеИмени);
		РасширениеФайла = СтрПолучитьСтроку(ПредставлениеИмени,СтрЧислоСтрок(ПредставлениеИмени));
	Иначе
		Шифрованное = ШифрованноеИмя;
		РасширениеФайла = Лев(ШифрованноеИмя, СтрНайти(ШифрованноеИмя, "_")-1);
	КонецЕсли;
	
 	МассивПодПутей = Новый Массив();
	МассивПодПутей.Добавить(РасширениеФайла);
	
	ДваСимволаКоличество = 2;
	
	сокрUUID = СокрЛП(сокрUUID);
	Длина = СтрДлина(сокрUUID);
	Для Счетчик = 1 По Длина Цикл
		ДваСимвола = СокрЛП(Сред(сокрUUID, Счетчик, ДваСимволаКоличество));
		Если ДваСимвола <> "" Тогда
			МассивПодПутей.Добавить(ДваСимвола);
		КонецЕсли;
		
		Счетчик = Счетчик + 1;
	КонецЦикла;
	
	Каталог = ?(ЭтоКартинкаВходящейПочты, ПолучитьУдаленнуюДиректориюДляКартинокПочты(), ПолучитьУдаленнуюДиректорию());
	Если НЕ ПроверитьСуществованиеКаталога(Каталог, СоздаватьКаталог) Тогда
		Возврат ПолучитьСкрытоеНазваниеСтарая(Название, UUID, ЭтоКартинкаВходящейПочты);
	КонецЕсли;
	
	Подкаталог = "";
	Для Каждого Элемент Из МассивПодПутей Цикл
		Подкаталог = Подкаталог + Элемент + "\";
		
		Если НЕ ПроверитьСуществованиеКаталога(Каталог + Подкаталог, СоздаватьКаталог) Тогда
			Возврат ПолучитьСкрытоеНазваниеСтарая(Название, UUID, ЭтоКартинкаВходящейПочты);
		КонецЕсли;
	КонецЦикла;
	
	Возврат Подкаталог + Шифрованное;
	
КонецФункции


// Функция - Получить шифрованное имя
//
// Параметры:
//  Название			 - Строка 
//  сокрUUID			 - Строка 
//  ПредставлениеИмени	 - Строка 
// 
// Возвращаемое значение:
//   Строка 
//
Функция ПолучитьШифрованноеИмя(Название, сокрUUID, ПредставлениеИмени = "") Экспорт
	
	// Удаляем черточки в UUID
	сокрUUID = СтрЗаменить(сокрUUID,"-","");
	ПредставлениеИмени = СтрЗаменить(Название,".",символы.ПС);
	ШифрованноеИмя = СтрПолучитьСтроку(ПредставлениеИмени,СтрЧислоСтрок(ПредставлениеИмени)) + "_" + сокрUUID;	
	
	Возврат ШифрованноеИмя;
	
КонецФункции

// Функция - Проверить существование каталога
//
// Параметры:
//  ИмяКаталога	 - Произвольный
// 
// Возвращаемое значение:
//   Произвольный 
//
Функция ПроверитьСуществованиеКаталога(ИмяКаталога, СоздаватьКаталог = Истина) Экспорт
	
	КаталогНаДиске = Новый Файл(ИмяКаталога);
    Если КаталогНаДиске.Существует() Тогда
        Возврат Истина;
	Иначе
		
		Если Не СоздаватьКаталог Тогда
			Возврат Ложь;
		КонецЕсли;
		
        СоздатьКаталог(ИмяКаталога);
		
		Если КаталогНаДиске.Существует() Тогда
			Возврат Истина;
        Иначе
            Возврат Ложь;
        КонецЕсли;
    КонецЕсли;
		
КонецФункции

// Функция получения названия файла из его имени и UUID
//
// Параметры:
//     Название - Произвольный 
//     UUID - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьСкрытоеНазваниеСтарая(Название, UUID, ЭтоКартинкаВходящегоПисьма = Ложь) Экспорт
	
	Если ЭтоКартинкаВходящегоПисьма Тогда
		Возврат ПолучитьСтароеНазваниеДляКартинокПочты(UUID);
	Иначе
		Возврат ПолучитьСтароеНазваниеДляФайлаХранилища(UUID, Название);
	КонецЕсли;
	
КонецФункции

Функция ПолучитьСтароеНазваниеДляФайлаХранилища(UUID, Название)
	
	// Удаляем черточки в UUID
	сокрUUID = СтрЗаменить(UUID,"-","");
	ПредставлениеИмени = СтрЗаменить(Название,".",символы.ПС);
	
	Шифрованное = СтрПолучитьСтроку(ПредставлениеИмени,СтрЧислоСтрок(ПредставлениеИмени)) + "_" + сокрUUID;
	Возврат Шифрованное;

КонецФункции

// Функция - Получить старое название для картинок почты
//
// Параметры:
//  Имя	 - Строка
// 
// Возвращаемое значение:
//   Строка 
//
Функция ПолучитьСтароеНазваниеДляКартинокПочты(Имя) Экспорт
	
   Имя = "_" + СтрЗаменить(Имя, "-", "");
    
   Возврат Имя;
	
КонецФункции

// Функция получения двоичных данных
//
// Параметры:
//     UUID - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьДвоичныеДанныеФайла(UUID) Экспорт
	
	Запрос = Новый Запрос;
	
	Запрос.Текст =                 
	" ВЫБРАТЬ   РАЗРЕШЕННЫЕ  
	|	ПрикрепленныеФайлы.Хранилище,
	|	ПрикрепленныеФайлы.Название,
	|	ПрикрепленныеФайлы.СпособХранения,
	|	ПрикрепленныеФайлы.ПутьДоФайла
	| ИЗ 
	|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
	| ГДЕ 
	|	ПрикрепленныеФайлы.UUID = &UUID";
	
	Запрос.УстановитьПараметр("UUID", UUID); 
	
	Выборка = Запрос.Выполнить().Выбрать();
	
	// Получаем двоичные данные
	ДвоичныеДанные = Неопределено;
	
	
	// Если не найдены файлы, тогд выходим из функции
	Если Не Выборка.Следующий() Тогда
		Возврат ДвоичныеДанные;
	КонецЕсли;  // Если Не Выборка.Следующий() Тогда
	
	
	// Выбираем файл, если он сохранился в информационной базе
	Если Выборка.СпособХранения = Перечисления.СпособХраненияФайла.ИнформационнаяБаза Тогда
		// Получаем адрес временного файла
		ВрФайл = КаталогВременныхФайлов() + Выборка.Название;
		// Записываем временный файл во временный каталог
		Попытка
			ДвоичныеДанные = Выборка.Хранилище.Получить();
		Исключение
			ИТ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОписаниеОшибки());
		КонецПопытки;
			
		
	ИначеЕсли Выборка.СпособХранения = Перечисления.СпособХраненияФайла.УдаленнаяДиректория Тогда  // Если ... = ИнформационнаяБаза Тогда
		
		// Получаем параметры удаленной директории
		УдаленнаяДиректория = ПолучитьУдаленнуюДиректорию();
		
		// Получаем двоичные данные файла
		Попытка
			ДвоичныеДанные = Новый ДвоичныеДанные( УдаленнаяДиректория + ?(Выборка.ПутьДоФайла = "",ПолучитьСкрытоеНазвание(Выборка.Название, UUID), Выборка.ПутьДоФайла ));
		Исключение
			ИТ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОписаниеОшибки());
		КонецПопытки;
			
		
		
	ИначеЕсли Выборка.СпособХранения = Перечисления.СпособХраненияФайла.ПроизвольнаяДиректория Тогда  // Если ... = УдаленнаяДиректория Тогда
		// Читаем удаленный файл
		Попытка
		ДвоичныеДанные = Новый ДвоичныеДанные( Выборка.ПутьДоФайла);
		Исключение
			ИТ_ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОписаниеОшибки());
		КонецПопытки;
			
		
	КонецЕсли;  // Если ... = ПроизвольнаяДиректория Тогда
	
	Возврат ДвоичныеДанные;
	
КонецФункции   // Функция ПолучитьДвоичныеДанныеФайла(UUID)


// Функция получения удаленной директории
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьУдаленнуюДиректорию() Экспорт
	
	УдаленнаяДиректория = ПолучениеЗначенийСервер.ПолучитьПараметр("ПутьКХранилищу");
	УдаленнаяДиректория = УдаленнаяДиректория + ?(Прав(УдаленнаяДиректория,1)="\","","\");
	
	Возврат УдаленнаяДиректория;
	
КонецФункции

Функция ПолучитьУдаленнуюДиректориюДляКартинокПочты()
	
	УдаленнаяДиректория = ПолучениеЗначенийСервер.ПолучитьПараметр("ИТ_ПутьККартинкамВходящейПочты");
	УдаленнаяДиректория = УдаленнаяДиректория + ?(Прав(УдаленнаяДиректория,1)="\","","\");
	
	Возврат УдаленнаяДиректория;
	
КонецФункции

// Функция получения имени файла по его uuid
//
// Параметры:
//     uuid - Произвольный
//
// Возвращаемое значение:
//    Произвольный
функция пфПолучитьИмяФайла(uuid) Экспорт
	Запрос = Новый Запрос;
	Запрос.Текст =                 
	" ВЫБРАТЬ   РАЗРЕШЕННЫЕ  
	|	ПрикрепленныеФайлы.Название
	| ИЗ 
	|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
	| ГДЕ 
	|	ПрикрепленныеФайлы.UUID = &UUID";
	
	Запрос.УстановитьПараметр("UUID", uuid);
	Выборка = Запрос.Выполнить().Выбрать();
	
	Если Не Выборка.Следующий() Тогда
		Возврат "";
	КонецЕсли;
	
	Возврат Выборка.Название;
КонецФункции


// Функция добавления файлов
// :
// - стрНеУдалить  - UUID файлов (разделённые '\r\n'), которые не надо удалять. Те файлы чьих uuid тут нету - УДАЛЯТС
// Я.
// параметры удаляемых файлов - многострочная строка в виде (UUID \r\n UUID...)
// - стрДобавить - параметры добавляемых файлов - многострочная строка в виде (путь \r\n имя  \r\n путь \r\n имя ...
// )
// :
// пустая строка :)
//
// Параметры:
//     стрНеУдалять - Произвольный 
//     стрДобавить - Произвольный 
//     Документ - Произвольный 
//     Автор - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция пфЗагрузитьФайлы(стрНеУдалять, стрДобавить, Документ, Автор = Неопределено) Экспорт
	
	Если Не ЗначениеЗаполнено(Автор)	Или ТипЗнч(Автор) = Тип("СправочникСсылка.Пользователи") Тогда
		
		Автор = ИТ_ГлобальныйМодульСервер.ИТ_глЗначениеПеременной("глТекущийПользователь");
	
	КонецЕсли;
	
	// Получаем все файлы прикреплённые к документу
	тзПрикрепленныеФайлы = пфПолучитьСписокПрикрепленныхФайлов(Документ);
	
	// Ищем строки для удаления
	удалять = Новый Массив;
	Для Каждого строка Из тзПрикрепленныеФайлы Цикл
		// Если uuid файла не найден в строке стрНеУдалять, то удаляем его 
		Если Найти(стрНеУдалять, строка["UUID"]) = 0 Тогда
			// ТзПрикрепленныеФайлы.Удалить(строка);
			удалять.Добавить(Истина);
		Иначе
			удалять.Добавить(Ложь);
		КонецЕсли;
	КонецЦикла;
	
	// Удаляем файлы
	инд = удалять.Количество()-1;
	Пока инд >= 0 Цикл
		Если Булево(удалять[инд]) Тогда
			тзПрикрепленныеФайлы.Удалить(инд);
		КонецЕсли;
		инд = инд-1;
	КонецЦикла;

	Инкремент = 2;
	
	// Добавляем новые файлы
	Если Не ПустаяСтрока(стрДобавить) Тогда
		способХранения = ?(Константы.ХранитьФайлыВПапке.Получить(), Перечисления.СпособХраненияФайла.УдаленнаяДиректория, Перечисления.СпособХраненияФайла.ИнформационнаяБаза);	
		индекс = 1;
		Пока индекс<СтрЧислоСтрок(стрДобавить) Цикл
			НоваяСтрока = тзПрикрепленныеФайлы.Добавить(); 	
			НоваяСтрока.Путь = СокрЛП(СтрПолучитьСтроку(стрДобавить, индекс));
			НоваяСтрока.Название = СокрЛП(СтрПолучитьСтроку(стрДобавить, индекс + 1));
			НоваяСтрока.Описание = "";
			НоваяСтрока.СпособХранения = способХранения;
			
			индекс = индекс + Инкремент;
		КонецЦикла;     	
	КонецЕсли;
	
	// Записываем изменения
	пфЗаписатьПрикрепленныеФайлы(Документ, тзПрикрепленныеФайлы, Автор);
	
	Возврат "";
КонецФункции


// Процедура выполняет действие:
//   Получить Данные Файла По G U I D
//
// Параметры:
//     GUID - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьДанныеФайлаПоGUID(GUID) Экспорт
	
	// Если GUID не заполнен, тогда выходим из процедуры
	Если Не ЗначениеЗаполнено(GUID) Тогда
		
		Возврат Неопределено;
		
	КонецЕсли;
	
	Запрос = Новый Запрос;
	
	Запрос.Текст =
	" ВЫБРАТЬ   РАЗРЕШЕННЫЕ  
	|	ПрикрепленныеФайлы.Хранилище,
	|	ПрикрепленныеФайлы.Название,
	|	ПрикрепленныеФайлы.СпособХранения,
	|	ПрикрепленныеФайлы.ПутьДоФайла
	| ИЗ 
	|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
	| ГДЕ 
	|	ПрикрепленныеФайлы.UUID = &GUID";
	
	Запрос.УстановитьПараметр("GUID", GUID); 
	
	Выборка = Запрос.Выполнить().Выбрать();
	Если Не Выборка.Следующий() Тогда
		
		Возврат Неопределено;
		
	КонецЕсли;
	
	// Получаем двоичные данные
	ДвоичныеДанные = Неопределено;
	
	// Выбираем файл, если он сохранился в информационной базе
	Если Выборка.СпособХранения = Перечисления.СпособХраненияФайла.ИнформационнаяБаза Тогда
		
		// Записываем временный файл во временный каталог
		Попытка
			
			ДвоичныеДанные = Выборка.Хранилище.Получить();
			
		Исключение
			
			Возврат Неопределено;
			
		КонецПопытки;
		
	ИначеЕсли Выборка.СпособХранения = Перечисления.СпособХраненияФайла.УдаленнаяДиректория Тогда  // Если ... = ИнформационнаяБаза Тогда
		
		// Получаем параметры удаленной директории
		УдаленнаяДиректория = Константы.ПутьКХранилищу.Получить();
		УдаленнаяДиректория = УдаленнаяДиректория + ?(Прав(УдаленнаяДиректория,1)="\","","\");
		
	
		Подкаталог = СокрЛП(ПрикрепленныеФайлыСервер.ПолучитьСкрытоеНазвание(Выборка.Название, GUID));
		ПутьДоХранилища = ПрикрепленныеФайлыСервер.ПолучитьУдаленнуюДиректорию() + Подкаталог;
	
		// Получаем двоичные данные файла
		Попытка
			
			ДвоичныеДанные = Новый ДвоичныеДанные( ПутьДоХранилища);
			
		Исключение
			
			Возврат Неопределено;
			
		КонецПопытки;
		
	ИначеЕсли Выборка.СпособХранения = Перечисления.СпособХраненияФайла.ПроизвольнаяДиректория Тогда  // Если ... = УдаленнаяДиректория Тогда
		// Читаем удаленный файл
		Попытка
			
			Если НЕ ЭтоАдресВременногоХранилища(Выборка.ПутьДоФайла) Тогда
				
				ДвоичныеДанные = Новый ДвоичныеДанные(Выборка.ПутьДоФайла);
				
			Иначе
				
				ДвоичныеДанные = Выборка.ПутьДоФайла;
				
			КонецЕсли;
			
		Исключение
			
			Возврат Неопределено;
			
		КонецПопытки;
		
	КонецЕсли;  // Если ... = ПроизвольнаяДиректория Тогда
	
	Если Не ДвоичныеДанные = Неопределено Тогда
		
		Возврат Новый Структура("ДвоичныеДанные, ИмяФайла",
		ДвоичныеДанные, Выборка.Название);
		
	КонецЕсли; 
	
	Возврат ДвоичныеДанные;
	
КонецФункции


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

	Возврат Новый Структура("СписокВыбора, ПоУмолчанию", СписокВыбора, ПоУмолчанию);
	
КонецФункции


// Формирует строку фильтра для диалога выбора картинки с типами файлов.
// 
// Нет.
// :
// Строка – фильтр по типам файлов для диалога выбора картинки.
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьФильтрИзображений() Экспорт

	Возврат "Все картинки (*.bmp;*.dib;*.rle;*.jpg;*.jpeg;*.tif;*.gif;*.png;*.ico;*.wmf;*.emf)|*.bmp;*.dib;*.rle;*.jpg;*.jpeg;*.tif;*.gif;*.png;*.ico;*.wmf;*.emf|" 
	      + "Формат bmp (*.bmp;*.dib;*.rle)|*.bmp;*.dib;*.rle|"
	      + "Формат jpeg (*.jpg;*.jpeg)|*.jpg;*.jpeg|"
	      + "Формат tiff (*.tif)|*.tif|"
	      + "Формат gif (*.gif)|*.gif|"
	      + "Формат png (*.png)|*.png|"
	      + "Формат icon (*.ico)|*.ico|"
	      + "Формат метафайл (*.wmf;*.emf)|*.wmf;*.emf|";

КонецФункции  // ПолучитьФильтрИзображений()


// Процедура выполняет действие:
//   Макс Размер Файла
//
// Возвращаемое значение:
//    Произвольный
Функция МаксРазмерФайла() Экспорт
	
	ЗначениеВМебибайтах = ИТ_ОбщегоНазначения.ПолучитьЗначениеКонстанты("ИТ_МаксимальныйРазмерФайла");
	Если ЗначениеВМебибайтах = Неопределено Тогда
		ЗначениеВМебибайтах = 0;
	КонецЕсли;
	
	МножительБайтов = 1048576;
	МножительКибиБайтов = 1024;
	
	Возврат Новый Структура("ВБайтах, ВКибиБайтах, ВМебибайтах", ЗначениеВМебибайтах * МножительБайтов, ЗначениеВМебибайтах * МножительКибиБайтов, ЗначениеВМебибайтах);
	
КонецФункции


// Процедура выполняет действие:
//   Тип Хранения Файла По Умолчанию
//
// Возвращаемое значение:
//    Произвольный
Функция ТипХраненияФайлаПоУмолчанию() Экспорт
	
	МассивРазрешенныхСпособов = Новый Массив;
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		" ВЫБРАТЬ   РАЗРЕШЕННЫЕ  
		|	Константы.ИТ_ХранитьФайлыВИБ КАК  ХранитьФайлыВИБ,
		|	Константы.ИТ_ХранитьФайлыСохранятьПуть КАК  ХранитьФайлыСохранятьПуть,
		|	Константы.ХранитьФайлыВПапке КАК  ХранитьФайлыВХранилище
		| ИЗ 
		|	Константы КАК  Константы";

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

	Выборка = Результат.Выбрать();

	Если Выборка.Следующий() Тогда
		
		Если Выборка.ХранитьФайлыВИБ = ИСТИНА Тогда
			МассивРазрешенныхСпособов.Добавить(Перечисления.СпособХраненияФайла.ИнформационнаяБаза);
		КонецЕсли;
		
		Если Выборка.ХранитьФайлыСохранятьПуть = ИСТИНА Тогда
			МассивРазрешенныхСпособов.Добавить(Перечисления.СпособХраненияФайла.ПроизвольнаяДиректория);
		КонецЕсли;
		
		Если Выборка.ХранитьФайлыВХранилище = ИСТИНА Тогда
			МассивРазрешенныхСпособов.Добавить(Перечисления.СпособХраненияФайла.УдаленнаяДиректория);
		КонецЕсли;
		
	КонецЕсли;
	
	Если МассивРазрешенныхСпособов.Количество() = 0 Тогда  // Нет разрешенных способов хранения
		Возврат Неопределено;
	ИначеЕсли МассивРазрешенныхСпособов.Количество() = 1 Тогда  // Способ хранения только один. Его и вернем.
		Возврат МассивРазрешенныхСпособов[0];
	Иначе  // Если разрешено хранение в хранилище, используем его по умолчанию. Если нет — сохраним в информ. базе
		Если МассивРазрешенныхСпособов.Найти(Перечисления.СпособХраненияФайла.УдаленнаяДиректория) <> Неопределено Тогда
			Возврат Перечисления.СпособХраненияФайла.УдаленнаяДиректория;
		Иначе
			Возврат Перечисления.СпособХраненияФайла.ИнформационнаяБаза;
		КонецЕсли;
	КонецЕсли;
	
	
КонецФункции

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

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

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

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


// Процедура выполняет действие:
//   Получить Размер Файла
//
// Параметры:
//     АдресФайла - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция ПолучитьРазмерФайла(АдресФайла) Экспорт
	РазмерФайла = 0;
	ЗначениеИзХранилища = ПолучитьИзВременногоХранилища(АдресФайла);
	Если ТипЗнч(ЗначениеИзХранилища) = Тип("ДвоичныеДанные")  ИЛИ  ТипЗнч(ЗначениеИзХранилища) = Тип("Файл") Тогда
		РазмерФайла = ЗначениеИзХранилища.Размер();
	КонецЕсли;
	Возврат РазмерФайла;
КонецФункции


// Процедура выполняет действие:
//   Файл Доступен С Сервера Предприятия
//
// Параметры:
//     ПутьКФайлу - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция ФайлДоступенССервераПредприятия(ПутьКФайлу) Экспорт
	ПроверяемыйФайл = Новый Файл(ПутьКФайлу);
	Если ПроверяемыйФайл.Существует() Тогда
		Возврат ИСТИНА;
	Иначе
		Возврат ЛОЖЬ;
	КонецЕсли;
КонецФункции


// Процедура выполняет действие:
//   Перенести Файлы Картинок Почты Во Внешнее Хранилище
//
// Параметры:
//     Хранилище - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Процедура ПеренестиФайлыКартинокПочтыВоВнешнееХранилище(Хранилище = Неопределено) экспорт

	Если Хранилище = Неопределено Тогда
    
    	Путь = ПолучениеЗначенийСервер.ПолучитьПараметр("ИТ_ПутьККартинкамВходящейПочты");
        
    Иначе
        
        Путь = Хранилище;
        
    КонецЕсли;
    
    Если Не ПустаяСтрока(Путь) Тогда
        
        Запрос = Новый Запрос;
        Запрос.Текст = 
        " ВЫБРАТЬ   РАЗРЕШЕННЫЕ  
        |   ЭлектронноеПисьмоВходящее.СтруктураКартинок,
        |   ЭлектронноеПисьмоВходящее.Ссылка
        | ИЗ 
        |   Документ.ЭлектронноеПисьмоВходящее КАК  ЭлектронноеПисьмоВходящее";
        
        РезультатЗапроса = Запрос.Выполнить();
        
        ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
        
        Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
            
            Структура = ВыборкаДетальныеЗаписи.СтруктураКартинок.Получить();
            
            Если Структура = Неопределено Тогда
            
            	Продолжить;
            
            КонецЕсли;
            
            НадоЗаписатьДокумент = Ложь;
            Для Каждого Пара Из Структура Цикл
                
                Если ТипЗнч(Пара.Значение.Картинка) = Тип("Картинка") Тогда
                    
                    НадоЗаписатьДокумент = Истина;
                    
                    Идентификатор = Строка(Новый УникальныйИдентификатор);
					СокращенныйИдентификатор = СтрЗаменить(Идентификатор, "-", "");
                    Имя = Пара.Значение.Расширение + "_" + СокращенныйИдентификатор;
           
					Подкаталог = ПрикрепленныеФайлыСервер.ПолучитьСкрытоеНазвание(Имя, Идентификатор, Имя, Истина, Истина);
					ИмяПолное = ПрикрепленныеФайлыСервер.ПолучитьИмяФайла( Путь,  Подкаталог );	
					
                    Попытка
                        
                        Пара.Значение.Картинка.Записать( ИмяПолное );
                        Пара.Значение.Картинка = Имя;
                        
                    Исключение
                        
                        ВызватьИсключение "Не удалось сохранить картинки по письму";
                        
                    КонецПопытки;
                    
                    
                КонецЕсли;
            
            КонецЦикла;
            
            Если НадоЗаписатьДокумент Тогда
            
            	Документ = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
                Документ.СтруктураКартинок = Новый ХранилищеЗначения(Структура);
                Документ.Записать();
            
            КонецЕсли;
            
        КонецЦикла;
        
    КонецЕсли;

КонецПроцедуры  // ()


// Функция получающая перечень файлов по перечню документов и спискуID
//
// Параметры:
//     ДокументыПеречень - Произвольный 
//     МассивUUID - Произвольный
//
// Возвращаемое значение:
//    Произвольный
Функция пфПолучитьСписокПрикрепленныхФайловПоПеречнюДокументовИСпискуID(ДокументыПеречень, МассивUUID) Экспорт
	
	Запрос = Новый Запрос;		
	НомерДокумента = 1;
			
	Для Каждого Документ Из ДокументыПеречень Цикл 
		
		
		ЗапросСсылкаНаДокумент= "";

		Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(Документ)) Тогда
		
			ЗапросСсылкаНаДокумент = " ПрикрепленныеФайлы.ИспользуемыйДокумент ССЫЛКА Справочник." + Документ.Метаданные().Имя + "  И  ";
		
		
		ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Документ)) Тогда
		
			ЗапросСсылкаНаДокумент = " ПрикрепленныеФайлы.ИспользуемыйДокумент ССЫЛКА Документ." + Документ.Метаданные().Имя+ "  И  ";
		
		
		КонецЕсли; 
		
		
		Запрос = Новый Запрос;
		Запрос.УстановитьПараметр("Ссылка"+ НомерДокумента, Документ);
		
		
		Запрос.Текст = Запрос.Текст + ?(Запрос.Текст = "", " ВЫБРАТЬ  РАЗРЕШЕННЫЕ  ", "  ОБЪЕДИНИТЬ   ВСЕ   ВЫБРАТЬ") + 
		" ПрикрепленныеФайлы.UUID,
		|	ПрикрепленныеФайлы.Название,
		|	ПрикрепленныеФайлы.Описание,
		|	ПрикрепленныеФайлы.ТипФайла КАК  ТипФайла,
		|	ПрикрепленныеФайлы.ДатаИзменения КАК  Дата,
		|	ПрикрепленныеФайлы.СпособХранения,
		|	 ЛОЖЬ  КАК  ПометкаУдаления
		| ИЗ 
		|	РегистрСведений.ПрикрепленныеФайлы КАК  ПрикрепленныеФайлы
		| ГДЕ 
		|	ПрикрепленныеФайлы.UUID В (&МассивUUID)  И  
		|	"+ ЗапросСсылкаНаДокумент + " ПрикрепленныеФайлы.ИспользуемыйДокумент = &Ссылка" + НомерДокумента ;
		
		
		НомерДокумента = НомерДокумента + 1;
		
	КонецЦикла;
	
	Запрос.УстановитьПараметр("МассивUUID",МассивUUID);
	
	
	тзПрикрепленныеФайлы = Запрос.Выполнить().Выгрузить();
		
	тзПрикрепленныеФайлы.Колонки.Добавить("Путь");
		
	Возврат тзПрикрепленныеФайлы;
	
КонецФункции


#КонецОбласти

#Область СлужебныйПрограммныйИнтерфейс

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// ПРОЦЕДУРЫ И ФУНКЦИИ РАБОТАЮЩИЕ С ФАЙЛАМИ
Функция ПолучитьСпособХранения()
	
	СпособХранения = Неопределено;
	Путь = "";
	
	Если ПолучениеЗначенийСервер.ПолучитьПараметр("ХранитьФайлыВПапке") Тогда
		
		Путь = ПолучениеЗначенийСервер.ПолучитьПараметр("ПутьКХранилищу");
		Если Не ПустаяСтрока(Путь) Тогда
			
			СпособХранения = Перечисления.СпособХраненияФайла.УдаленнаяДиректория;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если СпособХранения = Неопределено Тогда
		
		Если ПолучениеЗначенийСервер.ПолучитьПараметр("ИТ_ХранитьФайлыВИБ") Тогда
			
			СпособХранения = Перечисления.СпособХраненияФайла.ИнформационнаяБаза;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если СпособХранения = Неопределено Тогда
		
		Если ПолучениеЗначенийСервер.ПолучитьПараметр("ИТ_ХранитьФайлыСохранятьПуть") Тогда
			
			СпособХранения = Перечисления.СпособХраненияФайла.ПроизвольнаяДиректория;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если СпособХранения = Неопределено Тогда  // Нет способов хранения файлов
		
		Возврат Неопределено;
		
	КонецЕсли;
	
	Возврат Новый Структура("СпособХранения,Путь", СпособХранения, Путь);
	
КонецФункции

Процедура ЗаполнитьСтрокуИМенеджерЗаписиИзФормыПредпросмотра(Менеджер, СтрокаТаблицыФайлов, СтруктураСпособаХранения, СсылкаНаДокумент, ТекДата)
	
	Если ЛОЖЬ ТОГДА Менеджер = РегистрыСведений.ПрикрепленныеФайлы.СоздатьМенеджерЗаписи(); КонецЕсли;
	
	// ИмяФайла
	// ИДФайла
	// Действие
	// Путь
	// ЭтоНовыйФайл
	// АдресВХранилище
	
	
	// Документ
	// UUID
	// СпособХранения
	// Автор
	// ДатаИзменения
	// ДатаСоздания
	// Название
	// Описание
	// Редактор
	// Хранилище
	// ПутьДоФайла
	// ТипФайла
	
	ТекПользователь = ИТ_ГлобальныйМодульСервер.ИТ_глЗначениеПеременной("глТекущийПользователь");
	
    Менеджер.UUID           = Строка(Новый УникальныйИдентификатор);
    Менеджер.ИспользуемыйДокумент = СсылкаНаДокумент;
    Менеджер.СпособХранения = СтруктураСпособаХранения.СпособХранения;
    Менеджер.Автор          = ТекПользователь;
	Менеджер.ДатаИзменения  = ТекДата;
	Менеджер.ДатаСоздания   = ТекДата;
	Менеджер.Название       = СтрокаТаблицыФайлов.ИмяФайла;
	Менеджер.Описание       = "Файл прикреплен при предпросмотре отправляемого сообщения";
	Менеджер.Редактор       = ТекПользователь;
	// Пока не заполняется.
	// Менеджер.ТипФайла       = Справочники.ИТ_ТипыФайлов.
	
    СтрокаТаблицыФайлов.ИДФайла      = Менеджер.UUID;
    СтрокаТаблицыФайлов.ЭтоНовыйФайл = ЛОЖЬ;
	
	СтепеньСжатия6 = 6;
	
	Если СтруктураСпособаХранения.СпособХранения = Перечисления.СпособХраненияФайла.ИнформационнаяБаза Тогда
		
		// Тут всегда должен быть только адрес. иначе опять будет каша
		Если ЭтоАдресВременногоХранилища( СтрокаТаблицыФайлов.АдресВХранилище ) Тогда
			
			Менеджер.Хранилище   = Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(СтрокаТаблицыФайлов.АдресВХранилище), Новый СжатиеДанных(СтепеньСжатия6));
			
		Иначе
			
			ВызватьИсключение "Не переданны двоичные данные в запись файлов при предпросмотре отправляемого сообщения"
			
		КонецЕсли;
		
	ИначеЕсли  СтруктураСпособаХранения.СпособХранения = Перечисления.СпособХраненияФайла.УдаленнаяДиректория Тогда
		
		Менеджер.ПутьДоФайла = "";
        Менеджер.Хранилище   = Неопределено;
		
		// Тут всегда должен быть только адрес. иначе опять будет каша
		Если ЭтоАдресВременногоХранилища( СтрокаТаблицыФайлов.АдресВХранилище ) Тогда
		  
		  	Хранилище   = Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(СтрокаТаблицыФайлов.АдресВХранилище), Новый СжатиеДанных(СтепеньСжатия6));
			
			ЗаписатьФайлВПапку( Хранилище, Менеджер.Название, Менеджер.UUID, "" );
			
		Иначе
		  
		  	ВызватьИсключение "Не переданны двоичные данные в запись файлов при предпросмотре отправляемого сообщения"
		  
		КонецЕсли;
		
	ИначеЕсли  СтруктураСпособаХранения.СпособХранения = Перечисления.СпособХраненияФайла.ПроизвольнаяДиректория Тогда
		
        Менеджер.ПутьДоФайла = СтрокаТаблицыФайлов.Путь;
        Менеджер.Хранилище   = Неопределено;
		
	КонецЕсли;
	
КонецПроцедуры

// Возвращает имя файла, содержащего только допустимые символы
Функция пфПодготовитьИмяФайла(ИмяФайла)
	СокрИмяФайла = СокрП(ИмяФайла);
	
	НовоеИмя = "";
	Длина = СтрДлина(СокрИмяФайла);
	Позиция = 1;
	Пока Позиция <= Длина Цикл
		Символ = НРег(Сред(СокрИмяФайла, Позиция, 1));
		Если Найти("qwertyuiopasdfghjklzxcvbnmйцукенгшщзхъфывапролджэячсмитьбюё1234567890_ ", Символ) > 0 Тогда
			НовоеИмя = НовоеИмя + Символ;
		КонецЕсли;
		
		Позиция = Позиция + 1;
	КонецЦикла;
	
	Если ПустаяСтрока(НовоеИмя) Тогда
		НовоеИмя = "Стандартное имя файла";
	КонецЕсли;
	
	Возврат НовоеИмя;
КонецФункции

// Обрабатывает объект ИнтернетПочтовоеСообщение и подготовливает текстовый файл
Процедура пфОбработатьПисьмоКакФайл(Письмо, Файл, Источник)
	Имя = ?(Не ПустаяСтрока(Письмо.Тема), Письмо.Тема, Письмо.ИдентификаторСообщения);
	Получатели = "";
	Отправитель = Письмо.Отправитель.ОтображаемоеИмя + " <" + Письмо.Отправитель.Адрес + ">";
	ТекстПисьма = "";
	ДатаПолучения = Письмо.ДатаПолучения;
	ДатаОтправления = Письмо.ДатаОтправления;
	Важность = Строка(Письмо.Важность);
	Кодировка = Письмо.Кодировка;
	Копии = "";
	Вложения = "";
	
	Для Каждого Получатель Из Письмо.Получатели Цикл
		Получатели = Получатели + ?(Получатели <> "", ";", "") + Получатель.ОтображаемоеИмя + " <" + Получатель.Адрес + ">";
	КонецЦикла;
	
	Для Каждого Копия Из Письмо.Копии Цикл
		Копии = Копии + ?(Копии <> "", ";", "") + Копия.ОтображаемоеИмя + " <" + Копия.Адрес + ">";
	КонецЦикла;
	
	Для Каждого Вложение Из Письмо.Вложения Цикл
		Если ТипЗнч(Вложение.Данные) = Тип("ИнтернетПочтовоеСообщение") Тогда
			Вложения = Вложения + ?(Вложения <> "", ";", "") + пфПодготовитьИмяФайла(?(Не ПустаяСтрока(Вложение.Данные.Тема), Вложение.Данные.Тема, Вложение.Данные.ИдентификаторСообщения)) + ".txt";
		Иначе
			Вложения = Вложения + ?(Вложения <> "", ";", "") + Вложение.Имя;
		КонецЕсли;
	КонецЦикла;
	
	КодировкаФайла = "koi8-r";
	Для Каждого Текст Из Письмо.Тексты Цикл
		Если Текст.ТипТекста	= ТипТекстаПочтовогоСообщения.HTML Тогда
			ТекстПисьма	= ТекстПисьма + Символы.ПС + СокрЛП(ФормированиеСообщенийСервер.ВернутьТекстПисьмаВТекстовомФормате(Текст.Текст));
			Прервать;  // Обрабатываем загрузку сообщений, только один раз
		ИначеЕсли Текст.ТипТекста	= ТипТекстаПочтовогоСообщения.ПростойТекст Тогда
			ТекстПисьма	= ТекстПисьма + Символы.ПС + СокрЛП(Текст.Текст);
			ТекстПисьма = ПерестроитьМногострочныйТекст(ТекстПисьма);
			Прервать;  // Обрабатываем загрузку сообщений, только один раз
		ИначеЕсли Текст.ТипТекста	= ТипТекстаПочтовогоСообщения.РазмеченныйТекст Тогда
			ТекстПисьма	= ТекстПисьма + Символы.ПС + Текст.Текст;
			Прервать;  // Обрабатываем загрузку сообщений, только один раз
		КонецЕсли;
	КонецЦикла;
	
	ИмяФайла = КаталогВременныхФайлов() + пфПодготовитьИмяФайла(Имя) + ".eml";//".txt";
	Текст = Новый ЗаписьТекста(ИмяФайла, КодировкаФайла);
	Текст.ЗаписатьСтроку("Тема: " + Письмо.Тема);
	Текст.ЗаписатьСтроку("----------------");
	Текст.ЗаписатьСтроку("Отправитель: " + Отправитель);
	Текст.ЗаписатьСтроку("Получатели: " + Получатели);
	Текст.ЗаписатьСтроку("Получатели (копия): " + Копии);
	Текст.ЗаписатьСтроку("Дата отправления: " + ДатаОтправления);
	Текст.ЗаписатьСтроку("Дата получения: " + ДатаПолучения);
	Текст.ЗаписатьСтроку("Важность: " + Важность);
	Текст.ЗаписатьСтроку("----------------");
	Текст.ЗаписатьСтроку("Источник-вложение: " + Источник);
	Текст.ЗаписатьСтроку("Вложения: " + Вложения);
	Текст.ЗаписатьСтроку("----------------");
	Текст.ЗаписатьСтроку(ТекстПисьма);
	Текст.Закрыть();
	
	Файл.Описание = Имя;
	Файл.Название = пфПодготовитьИмяФайла(Имя) + ".eml";//".txt";
	Файл.Путь = ИмяФайла;
КонецПроцедуры

Функция ПерестроитьМногострочныйТекст(Текст) Экспорт
	МассивСимволов = Новый Массив;
	МассивСимволов.Добавить(Текст);

	ФормСтрока = Новый ФорматированнаяСтрока(МассивСимволов);
	
	ФормДок = Новый ФорматированныйДокумент;
	ФормДок.УстановитьФорматированнуюСтроку(ФормСтрока);
	Текст = ФормДок.ПолучитьТекст();
	Возврат Текст
КонецФункции


Процедура СохранитьВложенныеПисьма(Документ, 
					ТекущийПользователь, 
					ТекДата, 
					НаборЗаписей, 
					Письмо, 
					Источник = "", 
					ЭлектронноеПисьмо = Неопределено)
	
	Файл = пфПолучитьСтруктуруЗаписи();
	
	пфОбработатьПисьмоКакФайл(Письмо, Файл, Источник);
	ЗаписатьФайл(Документ, ТекущийПользователь, ТекДата, НаборЗаписей, Файл, ЭлектронноеПисьмо);
	
	Для Каждого Вложение Из Письмо.Вложения Цикл
		Если ТипЗнч(Вложение.Данные) = Тип("ИнтернетПочтовоеСообщение") Тогда
			СохранитьВложенныеПисьма(Документ, 
					ТекущийПользователь, 
					ТекДата, 
					НаборЗаписей, 
					Вложение.Данные, 
					Файл.Название, 
					ЭлектронноеПисьмо)
		Иначе
			СтепеньСжатия = 6;
			Файл.Описание = Вложение.Имя;
			Файл.Название = Вложение.ИмяФайла;
			Файл.Путь = Новый ХранилищеЗначения(Вложение.Данные, Новый СжатиеДанных(СтепеньСжатия));
			
			Файл.UUID = ПолучитьUUID();
			
			ЗаписатьФайл(Документ, ТекущийПользователь, ТекДата, НаборЗаписей, Файл);
		КонецЕсли;
	КонецЦикла;
	
	// Удаляем временный файл
	Попытка
		УдалитьФайлы(КаталогВременныхФайлов(), Файл.Название);
	Исключение
		Возврат;
	КонецПопытки;
КонецПроцедуры

Процедура ЗаписатьФайл(Документ, 
		ТекущийПользователь, 
		ТекДата, 
		НаборЗаписей, 
		Файл, 
		ЭлектронноеПисьмо = Неопределено,
		НовыйUUID = Неопределено)
	// Формируем новый UUID, если необходимо
	Если Файл.UUID = Неопределено ИЛИ Файл.UUID = "" Тогда
		Файл.UUID = ПолучитьUUID();
	КонецЕсли;
	Запись = НаборЗаписей.Добавить();
	
	// Записываем измерения 
	НовыйUUID = Файл.UUID;
	Запись.UUID = Файл.UUID;
	Запись.ИспользуемыйДокумент = Документ;

	// Записываем ресурсы
	Запись.Название 		= Файл.Название;
	Запись.Автор 			= ТекущийПользователь;
	Запись.ДатаСоздания 	= ТекДата;
	Запись.Редактор 		= ТекущийПользователь;
	Запись.ДатаИзменения    = ТекДата;
	Запись.Описание			= Файл.Описание;
	Запись.ТипФайла 		= Файл.ТипФайла;
	Запись.ЭлектронноеПисьмо = ЭлектронноеПисьмо;

	// Если файл требуется хранить в произвольном месте
	Если Файл.СпособХранения = Перечисления.СпособХраненияФайла.ПроизвольнаяДиректория Тогда
		
		// Указываем способ хранения файла
		Запись.СпособХранения = Перечисления.СпособХраненияФайла.ПроизвольнаяДиректория;

		Запись.ПутьДоФайла    = Файл.Путь;
		

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

// Функция записи файла в хранилище значений
Функция ПолучитьЗначениеДляХранилища(ПолноеИмяФайла)
	
	Хранилище = Неопределено;
	
	Если Не ПолноеИмяФайла = "" Тогда
		
		ДлинаСтроки	= СтрДлина(ПолноеИмяФайла);
		
		Для НомерСтроки = 0 По ДлинаСтроки - 1 Цикл
			
			СимволСтроки = Сред(ПолноеИмяФайла, ДлинаСтроки - НомерСтроки, 1);
			Если СимволСтроки = "\"  ИЛИ  СимволСтроки = "/" Тогда
				
				НачСимвол = ДлинаСтроки - НомерСтроки + 1;
				
				// Заполняем хранилище
				Попытка
					Данные = ПолучитьИзВременногоХранилища(ПолноеИмяФайла);
				Исключение
					Данные = Новый ДвоичныеДанные(ПолноеИмяФайла);
				КонецПопытки;
				СтепеньСжатия = 6;
				Хранилище = Новый ХранилищеЗначения(Данные, Новый СжатиеДанных(СтепеньСжатия));
				Прервать;
			КонецЕсли;
		КонецЦикла;
		
	КонецЕсли;
	
	Возврат Хранилище;
	
КонецФункции

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


#КонецОбласти