Files
SSL/SSL/src/CommonModules/РаботаСФайламиСлужебный/Module.bsl
T
2021-02-07 12:41:00 +03:00

9057 lines
608 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2021, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////
#Область СлужебныйПрограммныйИнтерфейс
// См. СозданиеНаОснованииПереопределяемый.ПриОпределенииОбъектовСКомандамиСозданияНаОсновании.
Процедура ПриОпределенииОбъектовСКомандамиСозданияНаОсновании(Объекты) Экспорт
Объекты.Добавить(Метаданные.Справочники.Файлы);
КонецПроцедуры
// См. ЗапретРедактированияРеквизитовОбъектовПереопределяемый.ПриОпределенииОбъектовСЗаблокированнымиРеквизитами.
Процедура ПриОпределенииОбъектовСЗаблокированнымиРеквизитами(Объекты) Экспорт
Объекты.Вставить(Метаданные.Справочники.УчетныеЗаписиСинхронизацииФайлов.ПолноеИмя(), "");
КонецПроцедуры
// См. ПоискИУдалениеДублей.ТипыИсключаемыеИзВозможныхДублей
Процедура ПриДобавленииТиповИсключаемыхИзВозможныхДублей(ИсключаемыеТипы) Экспорт
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(
ИсключаемыеТипы, Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип.Типы());
КонецПроцедуры
// Используется при выгрузке файлов для перехода в сервис (БТС).
//
// Параметры:
// ОбъектФайла - СправочникОбъект
// ИмяНовогоФайла - Строка
//
Процедура ВыгрузитьФайл(Знач ОбъектФайла, Знач ИмяНовогоФайла) Экспорт
Если ОбъектФайла.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
РаботаСФайламиВТомахСлужебный.СкопироватьФайл(ОбъектФайла.Ссылка, ИмяНовогоФайла);
Иначе
ДвоичныеДанныеФайла = РаботаСФайлами.ДвоичныеДанныеФайла(ОбъектФайла.Ссылка);
Попытка
ДвоичныеДанныеФайла.Записать(ИмяНовогоФайла);
Исключение
СообщениеОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru='Двоичные данные файла %1 были удалены. Возможно, файл очищен как ненужный или удален антивирусной программой.
|Обратитесь к администратору.'"), Строка(ОбъектФайла.Ссылка));
ВызватьИсключение СообщениеОбОшибке;
КонецПопытки;
КонецЕсли;
КонецПроцедуры
// Используется при загрузке файлов для переходе в сервис (БТС).
//
Процедура ЗагрузитьФайл(Знач ОбъектФайла, Знач ПутьКФайлу) Экспорт
ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу);
Если ТипХраненияФайлов() = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
РаботаСФайламиВТомахСлужебный.ДобавитьФайл(ОбъектФайла, ДвоичныеДанные, , Истина);
Иначе
ОбъектФайла.ДополнительныеСвойства.Вставить("ДвоичныеДанныеФайла", ДвоичныеДанные);
ОбъектФайла.ФайлХранилище = Новый ХранилищеЗначения(Неопределено);
ОбъектФайла.Том = Справочники.ТомаХраненияФайлов.ПустаяСсылка();
ОбъектФайла.ПутьКФайлу = "";
ОбъектФайла.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе;
КонецЕсли;
КонецПроцедуры
// Параметры:
// Результат - Структура
// ПрисоединенныйФайл - ОпределяемыйТип.ПрисоединенныйФайлОбъект
// ВерсияФайла - СправочникСсылка.ВерсииФайлов
//
Процедура ЗаполнитьДополнительныеДанныеФайла(Результат, ПрисоединенныйФайл, ВерсияФайла = Неопределено) Экспорт
СправочникПоддерживаетВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", Метаданные.НайтиПоТипу(ТипЗнч(ПрисоединенныйФайл)));
Если СправочникПоддерживаетВозможностьХранитьВерсии И ЗначениеЗаполнено(ПрисоединенныйФайл.ТекущаяВерсия) Тогда
ТекущаяВерсияФайла = ПрисоединенныйФайл.ТекущаяВерсия;
Иначе
ТекущаяВерсияФайла = ПрисоединенныйФайл.Ссылка;
КонецЕсли;
Результат.Вставить("ТекущаяВерсия", ТекущаяВерсияФайла);
Если ВерсияФайла <> Неопределено Тогда
Результат.Вставить("Версия", ВерсияФайла);
ИначеЕсли СправочникПоддерживаетВозможностьХранитьВерсии И ЗначениеЗаполнено(ПрисоединенныйФайл.ТекущаяВерсия) Тогда
Результат.Вставить("Версия", ПрисоединенныйФайл.ТекущаяВерсия);
Иначе
Результат.Вставить("Версия", ПрисоединенныйФайл.Ссылка);
КонецЕсли;
Если ЗначениеЗаполнено(ВерсияФайла) Тогда
ТекущаяВерсияОбъект = ВерсияФайла.ПолучитьОбъект();
Результат.Вставить("НомерВерсии", ТекущаяВерсияОбъект.НомерВерсии);
ТекущаяВерсияФайла = ВерсияФайла;
Иначе
Результат.Вставить("НомерВерсии", 0);
ТекущаяВерсияФайла = Результат.Версия;
ТекущаяВерсияОбъект = ПрисоединенныйФайл;
КонецЕсли;
Результат.Вставить("Наименование", ТекущаяВерсияОбъект.Наименование);
Результат.Вставить("Расширение", ТекущаяВерсияОбъект.Расширение);
Результат.Вставить("Размер", ТекущаяВерсияОбъект.Размер);
Результат.Вставить("ДатаМодификацииУниверсальная", ТекущаяВерсияОбъект.ДатаМодификацииУниверсальная);
Результат.Вставить("Том", ТекущаяВерсияОбъект.Том);
Результат.Вставить("Автор", ТекущаяВерсияОбъект.Автор);
Результат.Вставить("СтатусИзвлеченияТекста", ТекущаяВерсияОбъект.СтатусИзвлеченияТекста);
Результат.Вставить("ПолноеНаименованиеВерсии", СокрЛП(ТекущаяВерсияОбъект.Наименование));
СтруктураКлюча = Новый Структура("Файл", ТекущаяВерсияФайла);
КлючЗаписи = РегистрыСведений.ДвоичныеДанныеФайлов.СоздатьКлючЗаписи(СтруктураКлюча);
НавигационнаяСсылкаТекущейВерсии = ПолучитьНавигационнуюСсылку(КлючЗаписи, "ДвоичныеДанныеФайла");
Результат.Вставить("НавигационнаяСсылкаТекущейВерсии", НавигационнаяСсылкаТекущейВерсии);
КодировкаТекущейВерсии = РегистрыСведений.КодировкиФайлов.КодировкаВерсииФайла(ТекущаяВерсияФайла);
Результат.Вставить("КодировкаТекущейВерсии", КодировкаТекущейВерсии);
ТекущийПользователь = Пользователи.АвторизованныйПользователь();
НаЧтение = Результат.Редактирует <> ТекущийПользователь;
Результат.Вставить("НаЧтение", НаЧтение);
ВРабочемКаталогеНаЧтение = Истина;
ВРабочемКаталогеВладельца = Ложь;
ИмяКаталога = РабочийКаталогПользователя();
Если ЗначениеЗаполнено(ТекущаяВерсияФайла) Тогда
ПолноеИмяФайлаВРабочемКаталоге = РаботаСФайламиСлужебныйВызовСервера.ПолучитьПолноеИмяФайлаИзРегистра(ТекущаяВерсияФайла, ИмяКаталога, ВРабочемКаталогеНаЧтение, ВРабочемКаталогеВладельца);
Результат.Вставить("ПолноеИмяФайлаВРабочемКаталоге", ПолноеИмяФайлаВРабочемКаталоге);
КонецЕсли;
Результат.Вставить("ВРабочемКаталогеНаЧтение", ВРабочемКаталогеНаЧтение);
Результат.Вставить("РабочийКаталогВладельца", "");
РедактируетТекущийПользователь = (Результат.Редактирует = ТекущийПользователь);
Результат.Вставить("ФайлРедактируетТекущийПользователь", РедактируетТекущийПользователь);
СтатусИзвлеченияТекстаСтрока = "НеИзвлечен";
Если Результат.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен Тогда
СтатусИзвлеченияТекстаСтрока = "НеИзвлечен";
ИначеЕсли Результат.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.Извлечен Тогда
СтатусИзвлеченияТекстаСтрока = "Извлечен";
ИначеЕсли Результат.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.ИзвлечьНеУдалось Тогда
СтатусИзвлеченияТекстаСтрока = "ИзвлечьНеУдалось";
КонецЕсли;
Результат.Вставить("СтатусИзвлеченияТекста", СтатусИзвлеченияТекстаСтрока);
ПапкаДляСохранитьКак = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("НастройкиПрограммы", "ПапкаДляСохранитьКак");
Результат.Вставить("ПапкаДляСохранитьКак", ПапкаДляСохранитьКак);
КонецПроцедуры
// Процедура добавляет настройки специфичные для подсистемы Работа с файлами.
//
// Параметры:
// ОбщиеНастройки - Структура - настройки общие для всех пользователей.
// ПерсональныеНастройки - Структура - настройки различные для разных пользователей.
//
Процедура ДобавитьНастройкиРаботыСФайлами(ОбщиеНастройки, ПерсональныеНастройки) Экспорт
УстановитьОтключениеБезопасногоРежима(Истина);
УстановитьПривилегированныйРежим(Истина);
ПерсональныеНастройки.Вставить("ДействиеПоДвойномуЩелчкуМыши", ДействиеПоДвойномуЩелчкуМыши());
ПерсональныеНастройки.Вставить("СпособСравненияВерсийФайлов", СпособСравненияВерсийФайлов());
ПерсональныеНастройки.Вставить("СпрашиватьРежимРедактированияПриОткрытииФайла",
СпрашиватьРежимРедактированияПриОткрытииФайла());
ПерсональныеНастройки.Вставить("ВариантОткрытияФайла", ВариантОткрытияФайла());
ПерсональныеНастройки.Вставить("ЭтоПолноправныйПользователь",
Пользователи.ЭтоПолноправныйПользователь(,, Ложь));
ПоказыватьЗанятыеФайлыПриЗавершенииРаботы = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить(
"НастройкиПрограммы", "ПоказыватьЗанятыеФайлыПриЗавершенииРаботы");
Если ПоказыватьЗанятыеФайлыПриЗавершенииРаботы = Неопределено Тогда
ПоказыватьЗанятыеФайлыПриЗавершенииРаботы = Истина;
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить(
"НастройкиПрограммы",
"ПоказыватьЗанятыеФайлыПриЗавершенииРаботы",
ПоказыватьЗанятыеФайлыПриЗавершенииРаботы);
КонецЕсли;
ПерсональныеНастройки.Вставить("ПоказыватьЗанятыеФайлыПриЗавершенииРаботы",
ПоказыватьЗанятыеФайлыПриЗавершенииРаботы);
ПерсональныеНастройки.Вставить("ПоказыватьКолонкуРазмер", ПолучитьПоказыватьКолонкуРазмер());
КонецПроцедуры
// Получает все подчиненные файлы.
//
// Параметры:
// ВладелецФайла - ЛюбаяСсылка - владелец файла.
//
// Возвращаемое значение:
// Массив из СправочникСсылка.Файлы - массив файлов.
//
Функция ПолучитьВсеПодчиненныеФайлы(ВладелецФайла) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Файлы.Ссылка КАК Ссылка
|ИЗ
| Справочник.Файлы КАК Файлы
|ГДЕ
| Файлы.ВладелецФайла = &ВладелецФайла";
Запрос.УстановитьПараметр("ВладелецФайла", ВладелецФайла);
Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
КонецФункции
// Возвращает Истина, если файл с таким расширением можно загружать.
//
// Параметры:
// РасширениеФайла - Строка
// ВызыватьИсключение - Булево
//
// Возвращаемое значение:
// Булево
//
Функция ПроверитьРасширениеФайлаДляЗагрузки(РасширениеФайла, ВызыватьИсключение = Истина) Экспорт
ОбщиеНастройки = РаботаСФайламиСлужебныйПовтИсп.НастройкиРаботыСФайлами().ОбщиеНастройки;
Если НЕ ОбщиеНастройки.ЗапретЗагрузкиФайловПоРасширению Тогда
Возврат Истина;
КонецЕсли;
Если РаботаСФайламиСлужебныйКлиентСервер.РасширениеФайлаВСписке(
ОбщиеНастройки.СписокЗапрещенныхРасширений, РасширениеФайла) Тогда
Если ВызыватьИсключение Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Загрузка файлов с расширением ""%1"" запрещена.
|Обратитесь к администратору.'"),
РасширениеФайла);
Иначе
Возврат Ложь;
КонецЕсли;
КонецЕсли;
Возврат Истина;
КонецФункции
#Область ПроцедурыОбменаДанными
// Возвращает массив справочников, выступающих в роли владельцев файлов.
//
// Возвращаемое значение:
// Массив из ОбъектМетаданных
//
Функция СправочникиФайлов() Экспорт
Результат = Новый Массив();
КоллекцииМетаданных = Новый Массив();
КоллекцииМетаданных.Добавить(Метаданные.Справочники);
КоллекцииМетаданных.Добавить(Метаданные.Документы);
КоллекцииМетаданных.Добавить(Метаданные.БизнесПроцессы);
КоллекцииМетаданных.Добавить(Метаданные.Задачи);
КоллекцииМетаданных.Добавить(Метаданные.ПланыСчетов);
КоллекцииМетаданных.Добавить(Метаданные.ПланыОбмена);
КоллекцииМетаданных.Добавить(Метаданные.ПланыВидовХарактеристик);
КоллекцииМетаданных.Добавить(Метаданные.ПланыВидовРасчета);
Для Каждого КоллекцияМетаданных Из КоллекцииМетаданных Цикл
Для Каждого ОбъектМетаданных Из КоллекцияМетаданных Цикл
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ОбъектМетаданных.ПолноеИмя());
ПустаяСсылка = МенеджерОбъекта.ПустаяСсылка();
ИменаСправочниковХраненияФайлов = ИменаСправочниковХраненияФайлов(ПустаяСсылка, Истина);
Для Каждого ИмяСправочникаХраненияФайлов Из ИменаСправочниковХраненияФайлов Цикл
Результат.Добавить(Метаданные.Справочники[ИмяСправочникаХраненияФайлов.Ключ]);
КонецЦикла;
КонецЦикла;
КонецЦикла;
Результат.Добавить(Метаданные.Справочники.ВерсииФайлов);
Возврат Результат;
КонецФункции
// Возвращает массив объектов метаданных, которые используются для хранения
// двоичных данных файлов в информационной базе.
//
// Возвращаемое значение:
// Массив из ОбъектМетаданных
//
Функция ОбъектыХраненияФайловИнформационнойБазе() Экспорт
Результат = Новый Массив();
Результат.Добавить(Метаданные.РегистрыСведений.ДвоичныеДанныеФайлов);
Возврат Результат;
КонецФункции
// Возвращает расширение файла.
//
// Параметры:
// Объект - ОпределяемыйТип.ПрисоединенныйФайлОбъект
//
// Возвращаемое значение:
// Строка
//
Функция РасширениеФайла(Объект) Экспорт
Возврат Объект.Расширение;
КонецФункции
// Возвращает объекты, имеющие в наличии присоединенные (средствами подсистемы "Работа с файлами") файлы.
//
// Используется совместно с функцией ПрисоединенныеФайлы.СконвертироватьФайлыВПрисоединенные().
//
// Параметры:
// ТаблицаВладельцевФайлов - Строка - полное имя объекта метаданных,
// который может владеть присоединенными файлами.
//
// Возвращаемое значение:
// Массив
//
Функция СсылкиНаОбъектыСФайлами(Знач ТаблицаВладельцевФайлов) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ОбъектыСФайлами.Ссылка КАК Ссылка
|ИЗ
| &Таблица КАК ОбъектыСФайлами
|ГДЕ
| ИСТИНА В
| (ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| Справочник.Файлы КАК Файлы
| ГДЕ
| Файлы.ВладелецФайла = ОбъектыСФайлами.Ссылка)";
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&Таблица", ТаблицаВладельцевФайлов);
Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
КонецФункции
// Проверяет право текущего пользователя
// при использовании ограничения для папки или файла.
//
// Параметры:
// Папка - СправочникСсылка.ПапкиФайлов
// - СправочникСсылка.Файлы - папка файлов.
// - СправочникСсылка - владелец файлов.
//
// Места использования:
// РассылкаОтчетов.ЗаполнитьПараметрыРассылкиПараметрамиПоУмолчанию().
// Справочник.РассылкиОтчетов.Формы.ФормаЭлемента.ПравоИзмененияПапкиИФайлов().
//
Функция ПравоДобавленияФайловВПапку(Папка) Экспорт
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
Возврат МодульУправлениеДоступом.ЕстьПраво("ДобавлениеФайлов", Папка);
КонецЕсли;
Возврат Истина;
КонецФункции
// Записывает вложения в папку.
//
// Параметры:
// см. описание процедуры "ВыполнитьДоставку" модуля "РассылкаОтчетов".
//
Процедура ПриВыполненииДоставкиВПапку(ПараметрыДоставки, Вложения) Экспорт
// Перенос вложений в таблицу
УстановитьПривилегированныйРежим(Истина);
ТаблицаВложений = Новый ТаблицаЗначений;
ТаблицаВложений.Колонки.Добавить("ИмяФайла", Новый ОписаниеТипов("Строка"));
ТаблицаВложений.Колонки.Добавить("ПолныйПутьКФайлу", Новый ОписаниеТипов("Строка"));
ТаблицаВложений.Колонки.Добавить("Файл", Новый ОписаниеТипов("Файл"));
ТаблицаВложений.Колонки.Добавить("ФайлСсылка", Новый ОписаниеТипов("СправочникСсылка.Файлы"));
ТаблицаВложений.Колонки.Добавить("ИмяФайлаБезРасширения", Новый ОписаниеТипов("Строка"));
УстановитьПривилегированныйРежим(Ложь);
Для Каждого Вложение Из Вложения Цикл
СтрокаТаблицы = ТаблицаВложений.Добавить();
СтрокаТаблицы.ИмяФайла = Вложение.Ключ;
СтрокаТаблицы.ПолныйПутьКФайлу = Вложение.Значение;
СтрокаТаблицы.Файл = Новый Файл(СтрокаТаблицы.ПолныйПутьКФайлу);
СтрокаТаблицы.ИмяФайлаБезРасширения = СтрокаТаблицы.Файл.ИмяБезРасширения;
КонецЦикла;
// Поиск существующих файлов
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ РАЗЛИЧНЫЕ
| Файлы.Ссылка,
| Файлы.Наименование
|ИЗ
| Справочник.Файлы КАК Файлы
|ГДЕ
| Файлы.ВладелецФайла = &ВладелецФайла
| И Файлы.Наименование В(&МассивИменФайлов)";
Запрос.УстановитьПараметр("ВладелецФайла", ПараметрыДоставки.Папка);
Запрос.УстановитьПараметр("МассивИменФайлов", ТаблицаВложений.ВыгрузитьКолонку("ИмяФайлаБезРасширения"));
СуществующиеФайлы = Запрос.Выполнить().Выгрузить();
Для Каждого Файл Из СуществующиеФайлы Цикл
СтрокаТаблицы = ТаблицаВложений.Найти(Файл.Наименование, "ИмяФайлаБезРасширения");
СтрокаТаблицы.ФайлСсылка = Файл.Ссылка;
КонецЦикла;
Комментарий = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Рассылка отчетов ''%1'' от %2'"),
ПараметрыДоставки.Рассылка,
Формат(ПараметрыДоставки.ДатаВыполнения, "ДЛФ=DT"));
Для Каждого Вложение Из ТаблицаВложений Цикл
СведенияОФайле = РаботаСФайламиКлиентСервер.СведенияОФайле("ФайлСВерсией", Вложение.Файл);
СведенияОФайле.АдресВременногоХранилищаФайла = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(Вложение.ПолныйПутьКФайлу));
СведенияОФайле.ИмяБезРасширения = Вложение.ИмяФайлаБезРасширения;
СведенияОФайле.Комментарий = Комментарий;
// Запись
Если ЗначениеЗаполнено(Вложение.ФайлСсылка) Тогда
ВерсияСсылка = СоздатьВерсию(Вложение.ФайлСсылка, СведенияОФайле);
ОбновитьВерсиюВФайле(Вложение.ФайлСсылка, ВерсияСсылка, СведенияОФайле.АдресВременногоХранилищаТекста);
Иначе
Вложение.ФайлСсылка = РаботаСФайламиСлужебныйВызовСервера.СоздатьФайлСВерсией(ПараметрыДоставки.Папка, СведенияОФайле);
КонецЕсли;
// Заполнение ссылки на файл
Если ПараметрыДоставки.ДобавлятьСсылки <> "" Тогда
ПараметрыДоставки.ПредставлениеОтчетовПолучателя = СтрЗаменить(
ПараметрыДоставки.ПредставлениеОтчетовПолучателя,
Вложение.ПолныйПутьКФайлу,
ПолучитьНавигационнуюСсылкуИнформационнойБазы() + "#" + ПолучитьНавигационнуюСсылку(Вложение.ФайлСсылка));
КонецЕсли;
// Очистка
УдалитьИзВременногоХранилища(СведенияОФайле.АдресВременногоХранилищаФайла);
КонецЦикла;
КонецПроцедуры
// Устанавливает пометку удаления всем версиям указанного файла.
Процедура ПометитьНаУдалениеВерсииФайла(Знач ФайлСсылка, Знач ВерсияИсключение) Экспорт
Запрос = Новый Запрос(
"ВЫБРАТЬ
| ВерсииФайлов.Ссылка КАК Ссылка
|ИЗ
| Справочник.ВерсииФайлов КАК ВерсииФайлов
|ГДЕ
| ВерсииФайлов.Владелец = &Владелец
| И НЕ ВерсииФайлов.ПометкаУдаления
| И ВерсииФайлов.Ссылка <> &Исключение");
Запрос.УстановитьПараметр("Владелец", ФайлСсылка);
Запрос.УстановитьПараметр("Исключение", ВерсияИсключение);
ВыборкаВерсий = Запрос.Выполнить().Выгрузить();
НачатьТранзакцию();
Попытка
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("Справочник.ВерсииФайлов");
ЭлементБлокировки.УстановитьЗначение("Владелец", ФайлСсылка);
Блокировка.Заблокировать();
Для Каждого Версия Из ВыборкаВерсий Цикл
ВерсияОбъект = Версия.Ссылка.ПолучитьОбъект();
ВерсияОбъект.ПометкаУдаления = Истина;
ВерсияОбъект.ДополнительныеСвойства.Вставить("КонвертацияФайлов", Истина);
ВерсияОбъект.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
// Возвращает соответствие имен справочников и значения Булево
// для указанного владельца.
//
// Параметры:
// ВладелецФайлов - ЛюбаяСсылка - объект, к которому добавляется файл.
//
Функция ИменаСправочниковХраненияФайлов(ВладелецФайлов, НеВызыватьИсключение = Ложь) Экспорт
Если ТипЗнч(ВладелецФайлов) = Тип("Тип") Тогда
ТипВладельцаФайлов = ВладелецФайлов;
Иначе
ТипВладельцаФайлов = ТипЗнч(ВладелецФайлов);
КонецЕсли;
МетаданныеВладельца = Метаданные.НайтиПоТипу(ТипВладельцаФайлов);
ИменаСправочников = Новый Соответствие;
Если МетаданныеВладельца <> Неопределено Тогда
ИмяСтандартногоОсновногоСправочника = МетаданныеВладельца.Имя
+ ?(СтрЗаканчиваетсяНа(МетаданныеВладельца.Имя, "ПрисоединенныеФайлы"), "", "ПрисоединенныеФайлы");
Если Метаданные.Справочники.Найти(ИмяСтандартногоОсновногоСправочника) <> Неопределено Тогда
ИменаСправочников.Вставить(ИмяСтандартногоОсновногоСправочника, Истина);
ИначеЕсли Метаданные.ОпределяемыеТипы.ВладелецФайлов.Тип.СодержитТип(ТипВладельцаФайлов) Тогда
ИменаСправочников.Вставить("Файлы", Истина);
КонецЕсли;
// Переопределение стандартного справочника хранения присоединенных файлов.
РаботаСФайламиПереопределяемый.ПриОпределенииСправочниковХраненияФайлов(
ТипВладельцаФайлов, ИменаСправочников);
КонецЕсли;
ОсновнойСправочникУказан = Ложь;
Для каждого КлючИЗначение Из ИменаСправочников Цикл
Если Метаданные.Справочники.Найти(КлючИЗначение.Ключ) = Неопределено Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка при определении имен справочников для хранения файлов.
|У владельца файлов типа ""%1""
|указан несуществующий справочник ""%2"".'"),
Строка(ТипВладельцаФайлов),
Строка(КлючИЗначение.Ключ));
ИначеЕсли Не СтрЗаканчиваетсяНа(КлючИЗначение.Ключ, "ПрисоединенныеФайлы") И Не КлючИЗначение.Ключ ="Файлы" Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка при определении имен справочников для хранения файлов.
|У владельца файлов типа ""%1""
|указано имя справочника ""%2""
|без окончания ""ПрисоединенныеФайлы"".'"),
Строка(ТипВладельцаФайлов),
Строка(КлючИЗначение.Ключ));
ИначеЕсли КлючИЗначение.Значение = Неопределено Тогда
ИменаСправочников.Вставить(КлючИЗначение.Ключ, Ложь);
ИначеЕсли КлючИЗначение.Значение = Истина Тогда
Если ОсновнойСправочникУказан Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка при определении имен справочников для хранения файлов.
|У владельца файлов типа ""%1""
|основной справочник указан более одного раза.'"),
Строка(ТипВладельцаФайлов),
Строка(КлючИЗначение.Ключ));
КонецЕсли;
ОсновнойСправочникУказан = Истина;
КонецЕсли;
КонецЦикла;
Если ИменаСправочников.Количество() = 0 Тогда
Если НеВызыватьИсключение Тогда
Возврат ИменаСправочников;
КонецЕсли;
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка при определении имен справочников для хранения файлов.
|У владельца файлов типа ""%1""
|не имеется справочников для хранения файлов.'"),
Строка(ТипВладельцаФайлов));
КонецЕсли;
Возврат ИменаСправочников;
КонецФункции
// Создает у Получателя копии всех присоединенных файлов Источника.
// Источник и Получатель должны быть объектами одного типа.
//
// Параметры:
// Источник - ЛюбаяСсылка - объект, имеющий присоединенные файлы для копирования.
// Получатель - ЛюбаяСсылка - объект, к которому копируются присоединенные файлы.
//
Процедура СкопироватьПрисоединенныеФайлы(Знач Источник, Знач Получатель) Экспорт
ДоступнаЭлектроннаяПодпись = Неопределено;
МодульЭлектроннаяПодписьСлужебный = Неопределено;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
МодульЭлектроннаяПодписьСлужебный = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебный");
КонецЕсли;
КопируемыеФайлы = ВсеПодчиненныеФайлы(Источник.Ссылка);
Для Каждого КопируемыйФайл Из КопируемыеФайлы Цикл
Если ДоступнаЭлектроннаяПодпись = Неопределено Тогда
ДоступнаЭлектроннаяПодпись = (МодульЭлектроннаяПодписьСлужебный <> Неопределено)
И (МодульЭлектроннаяПодписьСлужебный.ДоступнаЭлектроннаяПодпись(ТипЗнч(КопируемыйФайл)));
КонецЕсли;
Если ОбщегоНазначения.ЗначениеРеквизитаОбъекта(КопируемыйФайл, "ПометкаУдаления") Тогда
Продолжить;
КонецЕсли;
НачатьТранзакцию();
Попытка
МенеджерОбъекта = ОбщегоНазначения.МенеджерОбъектаПоСсылке(КопируемыйФайл);
КопияФайла = КопируемыйФайл.Скопировать();
КопияФайлаСсылка = МенеджерОбъекта.ПолучитьСсылку();
КопияФайла.УстановитьСсылкуНового(КопияФайлаСсылка);
КопияФайла.ВладелецФайла = Получатель.Ссылка;
КопияФайла.Редактирует = Справочники.Пользователи.ПустаяСсылка();
КопияФайла.ТекстХранилище = КопируемыйФайл.ТекстХранилище;
КопияФайла.СтатусИзвлеченияТекста = КопируемыйФайл.СтатусИзвлеченияТекста;
КопияФайла.ФайлХранилище = КопируемыйФайл.ФайлХранилище;
ДвоичныеДанные = РаботаСФайлами.ДвоичныеДанныеФайла(КопируемыйФайл);
ТипХраненияФайла = ТипХраненияФайлов();
Если ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
КопияФайла.ТипХраненияФайла = ТипХраненияФайла;
ЗаписатьФайлВИнформационнуюБазу(КопияФайлаСсылка, ДвоичныеДанные);
Иначе
КопияФайла.Том = Неопределено;
КопияФайла.ПутьКФайлу = Неопределено;
КопияФайла.ТипХраненияФайла = Неопределено;
РаботаСФайламиВТомахСлужебный.ДобавитьФайл(КопияФайла, ДвоичныеДанные);
КонецЕсли;
КопияФайла.Записать();
Если ДоступнаЭлектроннаяПодпись Тогда
УстановленныеПодписи = МодульЭлектроннаяПодпись.УстановленныеПодписи(КопируемыйФайл);
МодульЭлектроннаяПодпись.ДобавитьПодпись(КопияФайла.Ссылка, УстановленныеПодписи);
СертификатыИсточника = МодульЭлектроннаяПодпись.СертификатыШифрования(КопируемыйФайл);
МодульЭлектроннаяПодпись.ЗаписатьСертификатыШифрования(КопияФайла, СертификатыИсточника);
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецЦикла;
КонецПроцедуры
// Возвращает структуру объекта файла.
//
Функция ФайлОбъект(Знач ПрисоединенныйФайл) Экспорт
ФайлОбъект = Неопределено;
МетаданныеОбъектаФайла = Метаданные.НайтиПоТипу(ТипЗнч(ПрисоединенныйФайл));
// Это справочник файлов.
Если ОбщегоНазначения.ЕстьРеквизитОбъекта("ВладелецФайла", МетаданныеОбъектаФайла) Тогда
// С возможностью хранить версии.
ЕстьТекущаяВерсия = Ложь;
Если ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", МетаданныеОбъектаФайла) Тогда
ТекущаяВерсия = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ПрисоединенныйФайл, "ТекущаяВерсия");
ЕстьТекущаяВерсия = ЗначениеЗаполнено(ТекущаяВерсия);
КонецЕсли;
Если ЕстьТекущаяВерсия Тогда
ФайлОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ТекущаяВерсия,
"Ссылка,ТипХраненияФайла,Наименование,Расширение,Том,ПутьКФайлу");
ФайлОбъект.Вставить("ВладелецФайла", ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ПрисоединенныйФайл, "ВладелецФайла"));
// Без возможности хранить версии.
Иначе
ФайлОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ПрисоединенныйФайл,
"Ссылка,ТипХраненияФайла,ВладелецФайла,Наименование,Расширение,Том,ПутьКФайлу");
КонецЕсли;
ЭтоГруппа = Ложь;
Если МетаданныеОбъектаФайла.Иерархический Тогда
ЭтоГруппа = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ПрисоединенныйФайл, "ЭтоГруппа");
КонецЕсли;
ФайлОбъект.Вставить("ЭтоГруппа", ЭтоГруппа);
// Это справочник версий файлов.
ИначеЕсли ОбщегоНазначения.ЕстьРеквизитОбъекта("РодительскаяВерсия", МетаданныеОбъектаФайла) Тогда
ФайлОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ПрисоединенныйФайл,
"Ссылка,ТипХраненияФайла,Наименование,Расширение,Том,ПутьКФайлу");
ФайлОбъект.Вставить("ВладелецФайла",
ОбщегоНазначения.ЗначениеРеквизитаОбъекта(
ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ПрисоединенныйФайл, "Владелец"), "ВладелецФайла"));
ФайлОбъект.Вставить("ЭтоГруппа", Ложь);
КонецЕсли;
Возврат ФайлОбъект;
КонецФункции
#КонецОбласти
#Область ОчисткаНенужныхФайлов
Функция ТекстЗапросаДляОчисткиФайлов(ВладелецФайла, Настройка, МассивИсключений, ЭлементИсключение, ДанныеДляОтчета = Ложь) Экспорт
ПолноеИмяСправочникаФайлов = Настройка.ТипВладельцаФайла.ПолноеИмя;
МетаданныеОбъектаФайлов = Метаданные.НайтиПоПолномуИмени(ПолноеИмяСправочникаФайлов);
ЕстьВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", МетаданныеОбъектаФайлов);
Если ЕстьВозможностьХранитьВерсии Тогда
СправочникВерсийФайлов = ОбщегоНазначения.ИдентификаторОбъектаМетаданных(МетаданныеОбъектаФайлов.Реквизиты.ТекущаяВерсия.Тип.Типы()[0]);
ПолноеИмяСправочникаВерсийФайлов = СправочникВерсийФайлов.ПолноеИмя;
Если Настройка.ПериодОчистки <> Перечисления.ПериодОчисткиФайлов.ПоПравилу Тогда
Если ДанныеДляОтчета Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) КАК ВладелецФайла,
| ВерсииФайлов.Размер /1024 /1024 КАК ОбъемНенужныхФайлов";
Иначе
ТекстЗапроса =
"ВЫБРАТЬ
| Файлы.Ссылка КАК ФайлСсылка,
| ВерсииФайлов.Ссылка КАК ВерсияСсылка";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
|ИЗ
| " + ПолноеИмяСправочникаФайлов + " КАК Файлы
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ " + ПолноеИмяСправочникаВерсийФайлов + " КАК ВерсииФайлов
| ПО Файлы.Ссылка = ВерсииФайлов.Владелец
|ГДЕ
| ВерсииФайлов.ДатаСоздания <= &ПериодОчистки
| И НЕ Файлы.ПометкаУдаления
| И ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) = &ТипВладельца
| И ВЫБОР
| КОГДА ВерсииФайлов.ТипХраненияФайла = ЗНАЧЕНИЕ(Перечисление.ТипыХраненияФайлов.ВТомахНаДиске)
| ТОГДА ВерсииФайлов.Том <> ЗНАЧЕНИЕ(Справочник.ТомаХраненияФайлов.ПустаяСсылка)
| ИЛИ (ВЫРАЗИТЬ(ВерсииФайлов.ПутьКФайлу КАК СТРОКА(100))) <> """"
| ИНАЧЕ ИСТИНА
| КОНЕЦ
| ";
Иначе
ТипОбъекта = ВладелецФайла;
ВсеСправочники = Справочники.ТипВсеСсылки();
ВсеДокументы = Документы.ТипВсеСсылки();
ТекстЗапроса = СтрЗаменить("ВЫБРАТЬ &ИмяТипаОбъекта", "&ИмяТипаОбъекта", ТипОбъекта.Имя + ".Ссылка,");
Если ВсеСправочники.СодержитТип(ТипЗнч(ТипОбъекта.ЗначениеПустойСсылки)) Тогда
Справочник = Метаданные.Справочники[ТипОбъекта.Имя];
Для Каждого Реквизит Из Справочник.Реквизиты Цикл
ТекстЗапроса = ТекстЗапроса + Символы.ПС + ТипОбъекта.Имя + "." + Реквизит.Имя + ",";
КонецЦикла;
ИначеЕсли
ВсеДокументы.СодержитТип(ТипЗнч(ТипОбъекта.ЗначениеПустойСсылки)) Тогда
Документ = Метаданные.Документы[ТипОбъекта.Имя];
Для Каждого Реквизит Из Документ.Реквизиты Цикл
Если Реквизит.Тип = Новый ОписаниеТипов("Дата") Тогда
ТекстЗапроса = ТекстЗапроса + Символы.ПС + "РАЗНОСТЬДАТ(" + Реквизит.Имя + ", &ТекущаяДата, ДЕНЬ) Как ДнейДоУдаленияОт" + Реквизит.Имя + ",";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + Символы.ПС + ТипОбъекта.Имя + "." + Реквизит.Имя + ",";
КонецЦикла;
КонецЕсли;
Если ДанныеДляОтчета Тогда
ТекстЗапроса = ТекстЗапроса + "
| ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) КАК ВладелецФайла,
| ВерсииФайлов.Размер /1024 /1024 КАК ОбъемНенужныхФайлов";
Иначе
ТекстЗапроса = ТекстЗапроса + "
| Файлы.Ссылка КАК ФайлСсылка,
| ВерсииФайлов.Ссылка КАК ВерсияСсылка";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
|ИЗ
| " + ТипОбъекта.ПолноеИмя+ " КАК " + ТипОбъекта.Имя + "
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ "+ ПолноеИмяСправочникаФайлов + " КАК Файлы
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ " + ПолноеИмяСправочникаВерсийФайлов + " КАК ВерсииФайлов
| ПО Файлы.Ссылка = ВерсииФайлов.Владелец
| ПО " + ТипОбъекта.Имя + ".Ссылка = Файлы.ВладелецФайла
|ГДЕ
| НЕ Файлы.ПометкаУдаления
| И НЕ ЕстьNull(ВерсииФайлов.ПометкаУдаления, Ложь)
| И ВЫБОР
| КОГДА ВерсииФайлов.ТипХраненияФайла = ЗНАЧЕНИЕ(Перечисление.ТипыХраненияФайлов.ВТомахНаДиске)
| ТОГДА ВерсииФайлов.Том <> ЗНАЧЕНИЕ(Справочник.ТомаХраненияФайлов.ПустаяСсылка)
| ИЛИ (ВЫРАЗИТЬ(ВерсииФайлов.ПутьКФайлу КАК СТРОКА(100))) <> """"
| ИНАЧЕ ИСТИНА
| КОНЕЦ
| И ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) = &ТипВладельца";
КонецЕсли;
Иначе
Если Настройка.ПериодОчистки <> Перечисления.ПериодОчисткиФайлов.ПоПравилу Тогда
Если ДанныеДляОтчета Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) КАК ВладелецФайла,
| Файлы.Размер /1024 /1024 КАК ОбъемНенужныхФайлов";
Иначе
ТекстЗапроса =
"ВЫБРАТЬ
| Файлы.Ссылка КАК ФайлСсылка";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
|ИЗ
| Справочник." + Настройка.ТипВладельцаФайла.Имя + " КАК Файлы
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ " + ВладелецФайла.ПолноеИмя + " КАК СправочникФайлы
| ПО Файлы.ВладелецФайла = СправочникФайлы.Ссылка
|ГДЕ
| Файлы.ДатаСоздания <= &ПериодОчистки
| И НЕ Файлы.ПометкаУдаления
| И ВЫБОР
| КОГДА Файлы.ТипХраненияФайла = ЗНАЧЕНИЕ(Перечисление.ТипыХраненияФайлов.ВТомахНаДиске)
| ТОГДА (ВЫРАЗИТЬ(Файлы.ПутьКФайлу КАК СТРОКА(100))) <> """"
| ИЛИ НЕ Файлы.Том = ЗНАЧЕНИЕ(Справочник.ТомаХраненияФайлов.ПустаяСсылка)
| ИНАЧЕ ИСТИНА
| КОНЕЦ
| И ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) = &ТипВладельца
| ";
Иначе
ТипОбъекта = ВладелецФайла;
ВсеСправочники = Справочники.ТипВсеСсылки();
ВсеДокументы = Документы.ТипВсеСсылки();
ТекстЗапроса =
"ВЫБРАТЬ
| СправочникФайлы.Ссылка,
| ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) КАК ВладелецФайла,
| Файлы.Размер /1024 /1024 КАК ОбъемНенужныхФайлов,";
Если ВсеСправочники.СодержитТип(ТипЗнч(ТипОбъекта.ЗначениеПустойСсылки)) Тогда
Справочник = Метаданные.Справочники[ТипОбъекта.Имя];
Для Каждого Реквизит Из Справочник.Реквизиты Цикл
ТекстЗапроса = ТекстЗапроса + Символы.ПС + "СправочникФайлы." + Реквизит.Имя + ",";
КонецЦикла;
ИначеЕсли ВсеДокументы.СодержитТип(ТипЗнч(ТипОбъекта.ЗначениеПустойСсылки)) Тогда
Документ = Метаданные.Документы[ТипОбъекта.Имя];
Для Каждого Реквизит Из Документ.Реквизиты Цикл
Если Реквизит.Тип = Новый ОписаниеТипов("Дата") Тогда
ТекстЗапроса = ТекстЗапроса + Символы.ПС + "РАЗНОСТЬДАТ(" + Реквизит.Имя + ", &ТекущаяДата, ДЕНЬ) Как ДнейДоУдаленияОт" + Реквизит.Имя + ",";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + Символы.ПС + "СправочникФайлы." + Реквизит.Имя + ",";
КонецЦикла;
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
| Файлы.Ссылка КАК ФайлСсылка
|ИЗ
| Справочник." + Настройка.ТипВладельцаФайла.Имя + " КАК Файлы
| ЛЕВОЕ СОЕДИНЕНИЕ " + ВладелецФайла.ПолноеИмя + " КАК СправочникФайлы
| ПО Файлы.ВладелецФайла = СправочникФайлы.Ссылка
|ГДЕ
| НЕ Файлы.ПометкаУдаления
| И ВЫБОР
| КОГДА Файлы.ТипХраненияФайла = ЗНАЧЕНИЕ(Перечисление.ТипыХраненияФайлов.ВТомахНаДиске)
| ТОГДА (ВЫРАЗИТЬ(Файлы.ПутьКФайлу КАК СТРОКА(100))) <> """"
| ИЛИ НЕ Файлы.Том = ЗНАЧЕНИЕ(Справочник.ТомаХраненияФайлов.ПустаяСсылка)
| ИНАЧЕ ИСТИНА
| КОНЕЦ
| И ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) = &ТипВладельца";
КонецЕсли;
КонецЕсли;
Если МассивИсключений.Количество() > 0 Тогда
ТекстЗапроса = ТекстЗапроса + "
| И НЕ Файлы.ВладелецФайла В ИЕРАРХИИ (&МассивИсключений)";
КонецЕсли;
Если ЭлементИсключение <> Неопределено Тогда
ТекстЗапроса = ТекстЗапроса + "
| И Файлы.ВладелецФайла В ИЕРАРХИИ (&ЭлементИсключение)";
КонецЕсли;
Если ЕстьВозможностьХранитьВерсии И Настройка.Действие = Перечисления.ВариантыОчисткиФайлов.ОчиститьВерсии Тогда
ТекстЗапроса = ТекстЗапроса + "
| И ВерсииФайлов.Ссылка <> Файлы.ТекущаяВерсия
| И ВерсииФайлов.РодительскаяВерсия <> ЗНАЧЕНИЕ(Справочник.ВерсииФайлов.ПустаяСсылка)";
КонецЕсли;
Возврат ТекстЗапроса;
КонецФункции
Функция ТекстЗапросаПолногоОбъемаФайлов() Экспорт
МетаданныеСправочники = Метаданные.Справочники;
ДобавитьПсевдонимПоля = Истина;
ТекстЗапроса = "";
Для Каждого Справочник Из МетаданныеСправочники Цикл
Если Справочник.Реквизиты.Найти("ВладелецФайла") <> Неопределено Тогда
ЕстьВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", Справочник);
Если ЕстьВозможностьХранитьВерсии Тогда
СправочникВерсийФайлов =
ОбщегоНазначения.ИдентификаторОбъектаМетаданных(Справочник.Реквизиты.ТекущаяВерсия.Тип.Типы()[0]);
ПолноеИмяСправочникаВерсийФайлов = СправочникВерсийФайлов.ПолноеИмя;
ЧастьТекстаЗапроса = "
|ВЫБРАТЬ
| ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) КАК ВладелецФайла,
| СУММА(ЕСТЬNULL(ВерсииФайлов.Размер, Файлы.Размер) / 1024 / 1024) КАК ОбъемВсего
|ИЗ
| #ИмяСправочника КАК Файлы
| ЛЕВОЕ СОЕДИНЕНИЕ #ПолноеИмяСправочникаВерсийФайлов КАК ВерсииФайлов
| ПО Файлы.Ссылка = ВерсииФайлов.Владелец
|ГДЕ
| НЕ Файлы.ПометкаУдаления
| И НЕ ЕСТЬNULL(ВерсииФайлов.ПометкаУдаления, ЛОЖЬ)
|
|СГРУППИРОВАТЬ ПО
| ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла)";
ЧастьТекстаЗапроса = СтрЗаменить(ЧастьТекстаЗапроса, "#ИмяСправочника", "Справочник." + Справочник.Имя);
ЧастьТекстаЗапроса = СтрЗаменить(ЧастьТекстаЗапроса, "#ПолноеИмяСправочникаВерсийФайлов",
ПолноеИмяСправочникаВерсийФайлов);
ТекстЗапроса = ТекстЗапроса + ?(ПустаяСтрока(ТекстЗапроса),"", " ОБЪЕДИНИТЬ ВСЕ ") + ЧастьТекстаЗапроса;
Если ДобавитьПсевдонимПоля Тогда
ДобавитьПсевдонимПоля = Ложь;
КонецЕсли;
Иначе
ТекстЗапроса = ТекстЗапроса + ?(ПустаяСтрока(ТекстЗапроса),"", " ОБЪЕДИНИТЬ ВСЕ") + "
|
|ВЫБРАТЬ
| ТИПЗНАЧЕНИЯ(Файлы.ВладелецФайла) " + ?(ДобавитьПсевдонимПоля, "КАК ВладелецФайла,",",") + "
| Файлы.Размер / 1024 / 1024 " + ?(ДобавитьПсевдонимПоля, "КАК ОбъемВсего","") + "
|ИЗ
| Справочник." + Справочник.Имя + " КАК Файлы
|ГДЕ
| НЕ Файлы.ПометкаУдаления";
Если ДобавитьПсевдонимПоля Тогда
ДобавитьПсевдонимПоля = Ложь;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат ТекстЗапроса;
КонецФункции
#КонецОбласти
#Область РаботаСТомамиФайлов
// Возвращает тип хранения файлов с учетом наличия томов.
// Если томов хранения файлов нет, тогда хранение в ИБ.
//
// Возвращаемое значение:
// ПеречислениеСсылка.ТипыХраненияФайлов
//
Функция ТипХраненияФайлов() Экспорт
Если РаботаСФайламиВТомахСлужебный.ХранитьФайлыВТомахНаДиске()
И РаботаСФайламиВТомахСлужебный.ЕстьТомаХраненияФайлов() Тогда
Возврат Перечисления.ТипыХраненияФайлов.ВТомахНаДиске;
Иначе
Возврат Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе;
КонецЕсли;
КонецФункции
// Проверяет, что хотя бы в одном томе есть хотя бы один файл.
//
// Возвращаемое значение:
// Булево
//
Функция ЕстьФайлыВТомах() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| СведенияОФайлах.Файл КАК Файл
|ИЗ
| РегистрСведений.СведенияОФайлах КАК СведенияОФайлах
|ГДЕ
| СведенияОФайлах.ТипХраненияФайла = ЗНАЧЕНИЕ(Перечисление.ТипыХраненияФайлов.ВТомахНаДиске)";
Возврат Не Запрос.Выполнить().Пустой();
КонецФункции
#КонецОбласти
#Область УправлениеДоступом
Функция ЭтоСправочникФайловИлиВерсийФайлов(ПолноеИмя) Экспорт
ЧастиИмени = СтрРазделить(ПолноеИмя, ".", Ложь);
Если ЧастиИмени.Количество() <> 2 Тогда
Возврат Ложь;
КонецЕсли;
Если ВРег(ЧастиИмени[0]) <> ВРег("Справочник")
И ВРег(ЧастиИмени[0]) <> ВРег("Catalog") Тогда
Возврат Ложь;
КонецЕсли;
Если СтрЗаканчиваетсяНа(ВРег(ЧастиИмени[1]), ВРег("ПрисоединенныеФайлы"))
Или ВРег(ЧастиИмени[1]) = ВРег("Файлы")
Или ВРег(ЧастиИмени[1]) = ВРег("ВерсииФайлов") Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
#КонецОбласти
#Область ЭлектроннаяПодписьИШифрование
Функция ДоступнаЭлектроннаяПодпись(ТипФайла) Экспорт
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
МодульЭлектроннаяПодписьСлужебный = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебный");
Возврат МодульЭлектроннаяПодписьСлужебный.ДоступнаЭлектроннаяПодпись(ТипФайла);
КонецЕсли;
Возврат Ложь;
КонецФункции
// Управляет видимостью элементов и команд в зависимости от наличия и
// использования электронной подписи и шифрования.
//
// Параметры:
// Форма - ФормаКлиентскогоПриложения
// ЭтоФормаСписка - Булево
// ТолькоКартинкаСтрок - Булево
//
Процедура КриптографияПриСозданииФормыНаСервере(Форма, ЭтоФормаСписка = Истина, ТолькоКартинкаСтрок = Ложь) Экспорт
Элементы = Форма.Элементы;
ЭлектронноеПодписание = Ложь;
Шифрование = Ложь;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
МодульЭлектроннаяПодписьСлужебный = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебный");
Если МодульЭлектроннаяПодписьСлужебный.ИспользоватьИнтерактивноеДобавлениеЭлектронныхПодписейИШифрование() Тогда
МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
ЭлектронноеПодписание = МодульЭлектроннаяПодпись.ИспользоватьЭлектронныеПодписи();
Шифрование = МодульЭлектроннаяПодпись.ИспользоватьШифрование();
КонецЕсли;
КонецЕсли;
Если ЭтоФормаСписка Тогда
Если ОбщегоНазначения.ЭтоСправочник(Метаданные.НайтиПоПолномуИмени(Форма.Список.ОсновнаяТаблица)) Тогда
ТаблицаФайлов = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(Форма.Список.ОсновнаяТаблица);
Доступна = ДоступнаЭлектроннаяПодпись(ТипЗнч(ТаблицаФайлов.ПустаяСсылка()));
Иначе
Доступна = Истина;
КонецЕсли;
Иначе
Доступна = ДоступнаЭлектроннаяПодпись(ТипЗнч(Форма.Объект.Ссылка));
КонецЕсли;
Используется = (ЭлектронноеПодписание Или Шифрование) И Доступна;
Если ЭтоФормаСписка Тогда
Элементы.СписокНомерКартинкиПодписанЗашифрован.Видимость = Используется;
КонецЕсли;
Если Не ТолькоКартинкаСтрок Тогда
Элементы.ФормаГруппаКомандЭлектроннаяПодписьИШифрование.Видимость = Используется;
Если ЭтоФормаСписка Тогда
Элементы.СписокКонтекстноеМенюГруппаКомандЭлектроннаяПодписьИШифрование.Видимость = Используется;
Иначе
Элементы.ГруппаЭлектронныеПодписи.Видимость = ЭлектронноеПодписание И Доступна;
Элементы.ГруппаСертификатыШифрования.Видимость = Шифрование И Доступна;
КонецЕсли;
КонецЕсли;
Если Не Используется Тогда
Возврат;
КонецЕсли;
Если Не ТолькоКартинкаСтрок Тогда
Элементы.ФормаГруппаКомандЭлектроннаяПодпись.Видимость = ЭлектронноеПодписание;
Элементы.ФормаГруппаКомандШифрование.Видимость = Шифрование;
Если ЭтоФормаСписка Тогда
Элементы.СписокКонтекстноеМенюГруппаКомандЭлектроннаяПодпись.Видимость = ЭлектронноеПодписание;
Элементы.СписокКонтекстноеМенюГруппаКомандШифрование.Видимость = Шифрование;
КонецЕсли;
КонецЕсли;
Если ЭлектронноеПодписание И Шифрование Тогда
Заголовок = НСтр("ru = 'Электронная подпись и шифрование'");
Подсказка = НСтр("ru = 'Наличие электронной подписи или шифрования'");
Картинка = БиблиотекаКартинок["ПодписанЗашифрованЗаголовок"];
ИначеЕсли ЭлектронноеПодписание Тогда
Заголовок = НСтр("ru = 'Электронная подпись'");
Подсказка = НСтр("ru = 'Наличие электронной подписи'");
Картинка = БиблиотекаКартинок["ПодписанЭП"];
Иначе // Шифрование
Заголовок = НСтр("ru = 'Шифрование'");
Подсказка = НСтр("ru = 'Наличие шифрования'");
Картинка = БиблиотекаКартинок["Зашифрован"];
КонецЕсли;
Если ЭтоФормаСписка Тогда
Элементы.СписокНомерКартинкиПодписанЗашифрован.КартинкаШапки = Картинка;
Элементы.СписокНомерКартинкиПодписанЗашифрован.Подсказка = Подсказка;
КонецЕсли;
Если Не ТолькоКартинкаСтрок Тогда
ГруппаКомандЭП = Элементы.ФормаГруппаКомандЭлектроннаяПодписьИШифрование; //ГруппаФормы
ГруппаКомандЭП.Заголовок = Заголовок;
ГруппаКомандЭП.Подсказка = Заголовок;
ГруппаКомандЭП.Картинка = Картинка;
Если ЭтоФормаСписка Тогда
КомандаСпискаЭП = Элементы.СписокКонтекстноеМенюГруппаКомандЭлектроннаяПодписьИШифрование; // КнопкаФормы
КомандаСпискаЭП.Заголовок = Заголовок;
КомандаСпискаЭП.Подсказка = Заголовок;
КомандаСпискаЭП.Картинка = Картинка;
КонецЕсли;
КонецЕсли;
МодульЭлектроннаяПодписьСлужебный = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебный");
МодульЭлектроннаяПодписьСлужебный.ОформитьСписокПодписей(Форма, "ЭлектронныеПодписи");
КонецПроцедуры
// Только для внутреннего использования.
//
// Параметры:
// ПодписиВФорме - ТаблицаЗначений
//
Процедура ПеренестиРезультатыПроверкиПодписей(ПодписиВФорме, ПодписанныйФайл) Экспорт
Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
Возврат;
КонецЕсли;
МодульЭлектроннаяПодписьСлужебный = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебный");
Если Не МодульЭлектроннаяПодписьСлужебный.ДоступнаЭлектроннаяПодпись(ТипЗнч(ПодписанныйФайл)) Тогда
Возврат;
КонецЕсли;
МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
ПодписиВОбъекте = МодульЭлектроннаяПодпись.УстановленныеПодписи(ПодписанныйФайл);
Если ПодписиВФорме.Количество() <> ПодписиВОбъекте.Количество() Тогда
Возврат; // Если объект был изменен, результаты проверки не переносятся.
КонецЕсли;
Если ПодписиВФорме.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Свойства = Новый Структура("ДатаПроверкиПодписи, ПодписьВерна", Null, Null);
ЗаполнитьЗначенияСвойств(Свойства, ПодписиВОбъекте[0]);
Если Свойства.ДатаПроверкиПодписи = Null
Или Свойства.ПодписьВерна = Null Тогда
Возврат; // Если в объекте нет реквизитов проверки, результаты проверки не переносятся.
КонецЕсли;
Для Каждого Строка Из ПодписиВФорме Цикл
СтрокаВОбъекте = ПодписиВОбъекте.Получить(ПодписиВФорме.Индекс(Строка));
Если Строка.ДатаПодписи <> СтрокаВОбъекте.ДатаПодписи
Или Строка.Комментарий <> СтрокаВОбъекте.Комментарий
Или Строка.КомуВыданСертификат <> СтрокаВОбъекте.КомуВыданСертификат И ЗначениеЗаполнено(СтрокаВОбъекте.КомуВыданСертификат)
Или Строка.Отпечаток <> СтрокаВОбъекте.Отпечаток И ЗначениеЗаполнено(СтрокаВОбъекте.Отпечаток)
Или Строка.УстановившийПодпись <> СтрокаВОбъекте.УстановившийПодпись Тогда
Возврат; // Если объект был изменен, результаты проверки не переносятся.
КонецЕсли;
КонецЦикла;
Свойства.Вставить("Отпечаток");
Свойства.Вставить("КомуВыданСертификат");
Для Каждого Строка Из ПодписиВФорме Цикл
СтрокаВОбъекте = ПодписиВОбъекте.Получить(ПодписиВФорме.Индекс(Строка));
ЗаполнитьЗначенияСвойств(Свойства, СтрокаВОбъекте);
ЕстьИзменения = Ложь;
Для Каждого КлючИЗначение Из Свойства Цикл
Если Строка[КлючИЗначение.Ключ] <> Свойства[КлючИЗначение.Ключ] Тогда
ЕстьИзменения = Истина;
КонецЕсли;
КонецЦикла;
Если Не ЕстьИзменения Тогда
Продолжить; // Не нужно устанавливать модифицированность, если результаты проверки совпадают.
КонецЕсли;
ЗаполнитьЗначенияСвойств(Свойства, Строка);
ЗаполнитьЗначенияСвойств(СтрокаВОбъекте, Свойства);
МодульЭлектроннаяПодпись.ОбновитьПодпись(ПодписанныйФайл, СтрокаВОбъекте);
КонецЦикла;
КонецПроцедуры
// Помещает шифрованные файлы в базу и ставит признак Зашифрован файлу и всем версиям.
//
// Параметры:
// ФайлСсылка - СправочникСсылка.Файлы - файл.
// Зашифровать - Булево - зашифровать файл, если Истина - иначе расшифровать.
// МассивДанныхДляЗанесенияВБазу - Массив из Структура
// УникальныйИдентификатор - УникальныйИдентификатор - уникальный идентификатор формы.
// ИмяРабочегоКаталога - Строка - рабочий каталог.
// МассивФайловВРабочемКаталогеДляУдаления - Массив - файлы, которые надо удалить из регистра.
// МассивОтпечатков - Массив - массив отпечатков сертификатов, использованных для шифрования.
//
Процедура ЗаписатьИнформациюОШифровании(ФайлСсылка, Зашифровать, МассивДанныхДляЗанесенияВБазу, УникальныйИдентификатор,
ИмяРабочегоКаталога, МассивФайловВРабочемКаталогеДляУдаления, МассивОтпечатков) Экспорт
НачатьТранзакцию();
Попытка
АдресВременногоХранилищаТекстаТекущейВерсии = "";
АдресВременногоХранилищаОсновногоФайла = "";
Для Каждого ДанныеДляЗаписиНаСервере Из МассивДанныхДляЗанесенияВБазу Цикл
Если ТипЗнч(ДанныеДляЗаписиНаСервере.ВерсияСсылка) <> Тип("СправочникСсылка.ВерсииФайлов") Тогда
АдресВременногоХранилищаОсновногоФайла = ДанныеДляЗаписиНаСервере.АдресВременногоХранилища;
Продолжить;
КонецЕсли;
АдресВременногоХранилища = ДанныеДляЗаписиНаСервере.АдресВременногоХранилища;
ВерсияСсылка = ДанныеДляЗаписиНаСервере.ВерсияСсылка; // СправочникСсылка.ВерсииФайлов
АдресВременногоХранилищаТекста = ДанныеДляЗаписиНаСервере.АдресВременногоХранилищаТекста;
Если ВерсияСсылка = ФайлСсылка.ТекущаяВерсия Тогда
АдресВременногоХранилищаТекстаТекущейВерсии = АдресВременногоХранилищаТекста;
КонецЕсли;
ПолноеИмяФайлаВРабочемКаталоге = "";
ВРабочемКаталогеНаЧтение = Истина; // не используется
ВРабочемКаталогеВладельца = Истина;
ПолноеИмяФайлаВРабочемКаталоге = РаботаСФайламиСлужебныйВызовСервера.ПолучитьПолноеИмяФайлаИзРегистра(ВерсияСсылка,
ИмяРабочегоКаталога, ВРабочемКаталогеНаЧтение, ВРабочемКаталогеВладельца);
Если Не ПустаяСтрока(ПолноеИмяФайлаВРабочемКаталоге) Тогда
МассивФайловВРабочемКаталогеДляУдаления.Добавить(ПолноеИмяФайлаВРабочемКаталоге);
КонецЕсли;
РаботаСФайламиСлужебныйВызовСервера.УдалитьИзРегистра(ВерсияСсылка);
СведенияОФайле = РаботаСФайламиКлиентСервер.СведенияОФайле("ФайлСВерсией");
СведенияОФайле.ИмяБезРасширения = ВерсияСсылка.ПолноеНаименование;
СведенияОФайле.Комментарий = ВерсияСсылка.Комментарий;
СведенияОФайле.АдресВременногоХранилищаФайла = АдресВременногоХранилища;
СведенияОФайле.РасширениеБезТочки = ВерсияСсылка.Расширение;
СведенияОФайле.ВремяИзменения = ВерсияСсылка.ДатаСоздания;
СведенияОФайле.ВремяИзмененияУниверсальное = ВерсияСсылка.ДатаМодификацииУниверсальная;
СведенияОФайле.Размер = ВерсияСсылка.Размер;
СведенияОФайле.ВремяИзмененияУниверсальное = ВерсияСсылка.ДатаМодификацииУниверсальная;
СведенияОФайле.НовыйСтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
СведенияОФайле.Зашифрован = Зашифровать;
СведенияОФайле.ХранитьВерсии = Ложь;
ОбновитьВерсиюФайла(ФайлСсылка, СведенияОФайле, ВерсияСсылка, УникальныйИдентификатор);
// Для варианта с хранением файлов на диске (на сервере) удаляем Файл из временного хранилища после получения.
Если Не ПустаяСтрока(ДанныеДляЗаписиНаСервере.АдресФайла) И ЭтоАдресВременногоХранилища(ДанныеДляЗаписиНаСервере.АдресФайла) Тогда
УдалитьИзВременногоХранилища(ДанныеДляЗаписиНаСервере.АдресФайла);
КонецЕсли;
КонецЦикла;
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка)).ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлСсылка);
БлокировкаДанных.Заблокировать();
ФайлОбъект = ФайлСсылка.ПолучитьОбъект();
ЗаблокироватьДанныеДляРедактирования(ФайлСсылка, , УникальныйИдентификатор);
ФайлОбъект.Зашифрован = Зашифровать;
ФайлОбъект.ТекстХранилище = Новый ХранилищеЗначения("");
ФайлОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
// Чтобы прошла запись ранее подписанного объекта.
ФайлОбъект.ДополнительныеСвойства.Вставить("ЗаписьПодписанногоОбъекта", Истина);
Если Зашифровать Тогда
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
МодульЭлектроннаяПодписьСлужебный = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебный");
МодульЭлектроннаяПодписьСлужебный.ДобавитьСертификатыШифрования(ФайлСсылка, МассивОтпечатков);
КонецЕсли;
Иначе
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
МодульЭлектроннаяПодписьСлужебный = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебный");
МодульЭлектроннаяПодписьСлужебный.ОчиститьСертификатыШифрования(ФайлСсылка);
КонецЕсли;
КонецЕсли;
МетаданныеФайла = Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка));
ИспользованиеПолнотекстовогоПоиска = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.Использовать;
Если Не Зашифровать И АдресВременногоХранилищаТекстаТекущейВерсии <> "" Тогда
Если МетаданныеФайла.ПолнотекстовыйПоиск = ИспользованиеПолнотекстовогоПоиска Тогда
РезультатИзвлеченияТекста = ИзвлечьТекст(АдресВременногоХранилищаТекстаТекущейВерсии);
ФайлОбъект.СтатусИзвлеченияТекста = РезультатИзвлеченияТекста.СтатусИзвлеченияТекста;
ФайлОбъект.ТекстХранилище = РезультатИзвлеченияТекста.ТекстХранилище;
Иначе
ФайлОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
ФайлОбъект.ТекстХранилище = Новый ХранилищеЗначения("");
КонецЕсли;
КонецЕсли;
МетаданныеФайла = Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка));
ВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", МетаданныеФайла);
Если Не ФайлОбъект.ХранитьВерсии Или (ВозможностьХранитьВерсии И Не ЗначениеЗаполнено(ФайлОбъект.ТекущаяВерсия)) Тогда
ОбновитьДвоичныеДанныеФайлаНаСервере(ФайлОбъект, АдресВременногоХранилищаОсновногоФайла);
КонецЕсли;
ФайлОбъект.Записать();
РазблокироватьДанныеДляРедактирования(ФайлСсылка, УникальныйИдентификатор);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Процедура ПроверитьФайлОбработан(ФайлСсылка, ИмяПроцедуры) Экспорт
ОбновлениеИнформационнойБазы.ПроверитьОбъектОбработан(ФайлСсылка,,
"РаботаСФайлами.ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведений",
ИмяПроцедуры);
КонецПроцедуры
#КонецОбласти
#Область КонтрольВеденияУчета
// См. КонтрольВеденияУчетаПереопределяемый.ПриОпределенииПроверок
Процедура ПриОпределенииПроверок(ГруппыПроверок, Проверки) Экспорт
РаботаСФайламиВТомахСлужебный.ПриОпределенииПроверок(ГруппыПроверок, Проверки);
КонецПроцедуры
#КонецОбласти
#Область ИзвлечениеТекстаДляПолнотекстовогоПоиска
Процедура ИзвлечьТекстИзФайлов() Экспорт
УстановитьПривилегированныйРежим(Истина);
Если Не ОбщегоНазначения.ЭтоWindowsСервер() Тогда
Возврат; // Извлечение текста работает только под Windows.
КонецЕсли;
ЗаписьЖурналаРегистрации(
НСтр("ru = 'Файлы.Извлечение текста'",
ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Информация,
,
,
НСтр("ru = 'Начато регламентное извлечения текста'"));
Запрос = Новый Запрос(ТекстЗапросаДляИзвлеченияТекста());
ФайлыДляИзвлеченияТекста = Запрос.Выполнить().Выгрузить();
Для Каждого ФайлБезТекста Из ФайлыДляИзвлеченияТекста Цикл
ФайлЗаблокирован = Ложь;
ИмяФайлаСДвоичнымиДанными = "";
Попытка
ИзвлечьТекстИзФайла(ФайлБезТекста, ФайлЗаблокирован, ИмяФайлаСДвоичнымиДанными);
Исключение
Если ФайлЗаблокирован Тогда
ПоляФайла = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлБезТекста.Ссылка,
"Наименование, Расширение");
ЗаписьЖурналаРегистрации(
НСтр("ru = 'Файлы.Извлечение текста'",
ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка,
,
,
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось выполнить регламентное извлечение текста из файла
|""%1""
|по причине:
|""%2"".'"),
ОбщегоНазначенияКлиентСервер.ПолучитьИмяСРасширением(ПоляФайла.Наименование, ПоляФайла.Расширение),
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()) ));
КонецЕсли;
КонецПопытки;
Если ЗначениеЗаполнено(ИмяФайлаСДвоичнымиДанными) Тогда
Файл = Новый Файл(ИмяФайлаСДвоичнымиДанными);
Если Файл.Существует() Тогда
Попытка
УдалитьФайлы(ИмяФайлаСДвоичнымиДанными);
Исключение
ЗаписьЖурналаРегистрации(НСтр("ru = 'Файлы.Извлечение текста'", ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецЕсли;
КонецЕсли;
КонецЦикла;
ЗаписьЖурналаРегистрации(
НСтр("ru = 'Файлы.Извлечение текста'",
ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Информация,
,
,
НСтр("ru = 'Закончено регламентное извлечение текста'"));
КонецПроцедуры
// Возвращает Истина, если текст из файлов извлекается на сервере, а не на клиенте.
//
// Возвращаемое значение:
// Булево - Ложь - если текст не извлекается на сервере,
// т.е. может и должен быть извлечен на клиенте.
//
Функция ИзвлекатьТекстыФайловНаСервере() Экспорт
УстановитьПривилегированныйРежим(Истина);
Возврат Константы.ИзвлекатьТекстыФайловНаСервере.Получить();
КонецФункции
// Записывает на сервер результат извлечения текста - извлеченный текст и СтатусИзвлеченияТекста.
Процедура ЗаписатьРезультатИзвлеченияТекста(ФайлИлиВерсияСсылка, РезультатИзвлечения,
АдресВременногоХранилищаТекста) Экспорт
МетаданныеФайла = ФайлИлиВерсияСсылка.Метаданные();
ИспользованиеПолнотекстовогоПоиска = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.Использовать;
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(МетаданныеФайла.ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлИлиВерсияСсылка);
Если Не ОбщегоНазначения.ЕстьРеквизитОбъекта("ВладелецФайла", МетаданныеФайла) Тогда
Владелец = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ФайлИлиВерсияСсылка, "Владелец");
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Владелец.Метаданные().ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", Владелец);
КонецЕсли;
НачатьТранзакцию();
Попытка
БлокировкаДанных.Заблокировать();
ЗаблокироватьДанныеДляРедактирования(ФайлИлиВерсияСсылка);
ФайлИлиВерсияОбъект = ФайлИлиВерсияСсылка.ПолучитьОбъект();
Если ФайлИлиВерсияОбъект <> Неопределено Тогда
Если Не ПустаяСтрока(АдресВременногоХранилищаТекста) Тогда
Если МетаданныеФайла.ПолнотекстовыйПоиск = ИспользованиеПолнотекстовогоПоиска Тогда
РезультатИзвлеченияТекста = ИзвлечьТекст(АдресВременногоХранилищаТекста);
ФайлИлиВерсияОбъект.СтатусИзвлеченияТекста = РезультатИзвлеченияТекста.СтатусИзвлеченияТекста;
ФайлИлиВерсияОбъект.ТекстХранилище = РезультатИзвлеченияТекста.ТекстХранилище;
Иначе
ФайлИлиВерсияОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
ФайлИлиВерсияОбъект.ТекстХранилище = Новый ХранилищеЗначения("");
КонецЕсли;
УдалитьИзВременногоХранилища(АдресВременногоХранилищаТекста);
КонецЕсли;
Если РезультатИзвлечения = "НеИзвлечен" Тогда
ФайлИлиВерсияОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
ИначеЕсли РезультатИзвлечения = "Извлечен" Тогда
ФайлИлиВерсияОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.Извлечен;
ИначеЕсли РезультатИзвлечения = "ИзвлечьНеУдалось" Тогда
ФайлИлиВерсияОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.ИзвлечьНеУдалось;
КонецЕсли;
ПриЗаписиИзвлеченногоТекста(ФайлИлиВерсияОбъект);
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
#КонецОбласти
#Область ПрочиеФункции
Функция СписокРасширенийДляПредпросмотра() Экспорт
// См. также перечисление ФорматКартинки.
РасширенияДляПредпросмотра = Новый СписокЗначений;
РасширенияДляПредпросмотра.Добавить("bmp");
РасширенияДляПредпросмотра.Добавить("emf");
РасширенияДляПредпросмотра.Добавить("gif");
РасширенияДляПредпросмотра.Добавить("ico");
РасширенияДляПредпросмотра.Добавить("icon");
РасширенияДляПредпросмотра.Добавить("jpg");
РасширенияДляПредпросмотра.Добавить("jpeg");
РасширенияДляПредпросмотра.Добавить("png");
РасширенияДляПредпросмотра.Добавить("tiff");
РасширенияДляПредпросмотра.Добавить("tif");
РасширенияДляПредпросмотра.Добавить("wmf");
Возврат РасширенияДляПредпросмотра;
КонецФункции
Функция СписокЗапрещенныхРасширений() Экспорт
СписокЗапрещенныхРасширений = Новый СписокЗначений;
СписокЗапрещенныхРасширений.Добавить("ade");
СписокЗапрещенныхРасширений.Добавить("adp");
СписокЗапрещенныхРасширений.Добавить("app");
СписокЗапрещенныхРасширений.Добавить("bas");
СписокЗапрещенныхРасширений.Добавить("bat");
СписокЗапрещенныхРасширений.Добавить("chm");
СписокЗапрещенныхРасширений.Добавить("class");
СписокЗапрещенныхРасширений.Добавить("cmd");
СписокЗапрещенныхРасширений.Добавить("com");
СписокЗапрещенныхРасширений.Добавить("cpl");
СписокЗапрещенныхРасширений.Добавить("crt");
СписокЗапрещенныхРасширений.Добавить("dll");
СписокЗапрещенныхРасширений.Добавить("exe");
СписокЗапрещенныхРасширений.Добавить("fxp");
СписокЗапрещенныхРасширений.Добавить("hlp");
СписокЗапрещенныхРасширений.Добавить("hta");
СписокЗапрещенныхРасширений.Добавить("ins");
СписокЗапрещенныхРасширений.Добавить("isp");
СписокЗапрещенныхРасширений.Добавить("jse");
СписокЗапрещенныхРасширений.Добавить("js");
СписокЗапрещенныхРасширений.Добавить("lnk");
СписокЗапрещенныхРасширений.Добавить("mda");
СписокЗапрещенныхРасширений.Добавить("mdb");
СписокЗапрещенныхРасширений.Добавить("mde");
СписокЗапрещенныхРасширений.Добавить("mdt");
СписокЗапрещенныхРасширений.Добавить("mdw");
СписокЗапрещенныхРасширений.Добавить("mdz");
СписокЗапрещенныхРасширений.Добавить("msc");
СписокЗапрещенныхРасширений.Добавить("msi");
СписокЗапрещенныхРасширений.Добавить("msp");
СписокЗапрещенныхРасширений.Добавить("mst");
СписокЗапрещенныхРасширений.Добавить("ops");
СписокЗапрещенныхРасширений.Добавить("pcd");
СписокЗапрещенныхРасширений.Добавить("pif");
СписокЗапрещенныхРасширений.Добавить("prf");
СписокЗапрещенныхРасширений.Добавить("prg");
СписокЗапрещенныхРасширений.Добавить("reg");
СписокЗапрещенныхРасширений.Добавить("scf");
СписокЗапрещенныхРасширений.Добавить("scr");
СписокЗапрещенныхРасширений.Добавить("sct");
СписокЗапрещенныхРасширений.Добавить("shb");
СписокЗапрещенныхРасширений.Добавить("shs");
СписокЗапрещенныхРасширений.Добавить("url");
СписокЗапрещенныхРасширений.Добавить("vb");
СписокЗапрещенныхРасширений.Добавить("vbe");
СписокЗапрещенныхРасширений.Добавить("vbs");
СписокЗапрещенныхРасширений.Добавить("wsc");
СписокЗапрещенныхРасширений.Добавить("wsf");
СписокЗапрещенныхРасширений.Добавить("wsh");
Возврат СписокЗапрещенныхРасширений;
КонецФункции
Функция СписокРасширенийТекстовыхФайлов() Экспорт
Возврат "TXT XML INI";
КонецФункции
Функция ПодготовитьСтруктуруПараметровОтправки() Экспорт
Возврат Новый Структура("Получатель,Тема,Текст", Неопределено, "", "");
КонецФункции
Процедура РегламентнаяСинхронизацияФайловWebdav(Параметры = Неопределено, АдресРезультата = Неопределено) Экспорт
ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(Метаданные.РегламентныеЗадания.СинхронизацияФайлов);
УстановитьПривилегированныйРежим(Истина);
УдалитьНесинхронизируемыеФайлы();
Результат = УчетныеЗаписиСинхронизации();
Для каждого Выборка Из Результат Цикл
Если ПустаяСтрока(Выборка.Сервис) Тогда
Продолжить;
КонецЕсли;
СинхронизироватьФайлыСОблачнымСервисом(Выборка.Ссылка);
КонецЦикла;
КонецПроцедуры
// Заполняет список указанными типами файлов. Значение элемента списка
// используется в функции РаботаСФайламиСлужебныйКлиент.РасширенияПоТипуФайла
// для сопоставления возможных расширений известному типу файлов.
//
// Параметры:
// Список - СписокЗначений - список, в который будут добавлены поддерживаемые
// типы файлов.
//
Процедура ЗаполнитьСписокТипамиФайлов(Список) Экспорт
Список.Добавить("Изображения", НСтр("ru = 'Изображения (JPG, JPEG, PNG ...)'"));
Список.Добавить("ОфисныеДокументы", НСтр("ru = 'Офисные документы (DOC, DOCX, XLS ...)'"));
КонецПроцедуры
#КонецОбласти
#Область ОбменФайлами
// Подготовка параметров и предварительные проверки перед созданием файлового начального образа.
//
Функция ПодготовитьДанныеДляСозданияФайловогоНачальногоОбраза(СтруктураПараметров) Экспорт
Результат = Новый Структура("ДанныеПодготовлены, ТребуетсяПодтверждение, ТекстВопроса", Истина, Ложь, "");
ПолноеИмяФайловойБазыWindows = СтруктураПараметров.ПолноеИмяФайловойБазыWindows;
ПолноеИмяФайловойБазыLinux = СтруктураПараметров.ПолноеИмяФайловойБазыLinux;
ПутьКАрхивуСФайламиТомовWindows = СтруктураПараметров.ПутьКАрхивуСФайламиТомовWindows;
ПутьКАрхивуСФайламиТомовLinux = СтруктураПараметров.ПутьКАрхивуСФайламиТомовLinux;
ПутьКАрхивуСФайламиТомов = "";
ПолноеИмяФайловойБазы = "";
ЕстьФайлыВТомах = Ложь;
Если РаботаСФайлами.ЕстьТомаХраненияФайлов() Тогда
ЕстьФайлыВТомах = ЕстьФайлыВТомах();
КонецЕсли;
Если ОбщегоНазначения.ЭтоWindowsСервер() Тогда
ПутьКАрхивуСФайламиТомов = ПутьКАрхивуСФайламиТомовWindows;
ПолноеИмяФайловойБазы = ПолноеИмяФайловойБазыWindows;
Если Не ОбщегоНазначения.ИнформационнаяБазаФайловая() Тогда
Если ЕстьФайлыВТомах И Не ПустаяСтрока(ПутьКАрхивуСФайламиТомов) И (Лев(ПутьКАрхивуСФайламиТомов, 2) <> "\\"
ИЛИ СтрНайти(ПутьКАрхивуСФайламиТомов, ":") <> 0) Тогда
ОбщегоНазначения.СообщитьПользователю(
НСтр("ru = 'Путь к архиву с файлами томов должен быть задан
|в формате UNC (\\servername\resource)'"),
,
"ПутьКАрхивуСФайламиТомовWindows");
Результат.ДанныеПодготовлены = Ложь;
КонецЕсли;
Если Не ПустаяСтрока(ПолноеИмяФайловойБазы) И (Лев(ПолноеИмяФайловойБазы, 2) <> "\\" ИЛИ СтрНайти(ПолноеИмяФайловойБазы, ":") <> 0) Тогда
ОбщегоНазначения.СообщитьПользователю(
НСтр("ru = 'Путь к файловой информационной базе должен быть задан
|в формате UNC (\\servername\resource)'"),
,
"ПолноеИмяФайловойБазыWindows");
Результат.ДанныеПодготовлены = Ложь;
КонецЕсли;
КонецЕсли;
Иначе
ПутьКАрхивуСФайламиТомов = ПутьКАрхивуСФайламиТомовLinux;
ПолноеИмяФайловойБазы = ПолноеИмяФайловойБазыLinux;
КонецЕсли;
Если ПустаяСтрока(ПолноеИмяФайловойБазы) Тогда
ОбщегоНазначения.СообщитьПользователю(
НСтр("ru = 'Укажите полное имя файловой базы (файл 1cv8.1cd)'"),,
"ПолноеИмяФайловойБазыWindows");
Результат.ДанныеПодготовлены = Ложь;
ИначеЕсли Результат.ДанныеПодготовлены Тогда
ФайлБазы = Новый Файл(ПолноеИмяФайловойБазы);
Если ЕстьФайлыВТомах Тогда
Если ПустаяСтрока(ПутьКАрхивуСФайламиТомов) Тогда
ОбщегоНазначения.СообщитьПользователю(
НСтр("ru = 'Укажите полное имя архива с файлами томов (файл *.zip)'"),,
"ПутьКАрхивуСФайламиТомовWindows");
Результат.ДанныеПодготовлены = Ложь;
Иначе
Файл = Новый Файл(ПутьКАрхивуСФайламиТомов);
Если Файл.Существует() И ФайлБазы.Существует() Тогда
Результат.ТекстВопроса = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Файлы ""%1"" и ""%2"" уже существуют.
|Заменить существующие файлы?'"), ПутьКАрхивуСФайламиТомов, ПолноеИмяФайловойБазы);
Результат.ТребуетсяПодтверждение = Истина;
ИначеЕсли Файл.Существует() Тогда
Результат.ТекстВопроса = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Файл ""%1"" уже существует.
|Заменить существующий файл?'"), ПутьКАрхивуСФайламиТомов);
Результат.ТребуетсяПодтверждение = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Результат.ДанныеПодготовлены Тогда
Если ФайлБазы.Существует() И НЕ Результат.ТребуетсяПодтверждение Тогда
Результат.ТекстВопроса = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Файл ""%1"" уже существует.
|Заменить существующий файл?'"), ПолноеИмяФайловойБазы);
Результат.ТребуетсяПодтверждение = Истина;
КонецЕсли;
// Создать временный каталог.
ИмяКаталога = ПолучитьИмяВременногоФайла();
СоздатьКаталог(ИмяКаталога);
// Создать временный каталог для файлов.
ИмяКаталогаФайлов = ПолучитьИмяВременногоФайла();
СоздатьКаталог(ИмяКаталогаФайлов);
// Для передачи пути каталога файлов в обработчик ПриОтправкеДанныхФайла.
СохранитьНастройку("ОбменФайлами", "ВременныйКаталог", ИмяКаталогаФайлов);
// Добавляем в параметры переменные, которые потребуются для создания начального образа.
СтруктураПараметров.Вставить("ИмяКаталога", ИмяКаталога);
СтруктураПараметров.Вставить("ИмяКаталогаФайлов", ИмяКаталогаФайлов);
СтруктураПараметров.Вставить("ЕстьФайлыВТомах", ЕстьФайлыВТомах);
СтруктураПараметров.Вставить("ПутьКАрхивуСФайламиТомов", ПутьКАрхивуСФайламиТомов);
СтруктураПараметров.Вставить("ПолноеИмяФайловойБазы", ПолноеИмяФайловойБазы);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Процедура - Создать файловый начальный образ на сервере
//
// Параметры:
// Параметры - Структура:
// * ИмяКаталога - Строка
// * Язык - Строка
// * ПутьКАрхивуСФайламиТомов - Строка
// * ЕстьФайлыВТомах- Булево
// * ИмяКаталогаФайлов - Строка
// * ПолноеИмяФайловойБазы - Строка
// АдресХранилища - УникальныйИдентификатор
//
Процедура СоздатьФайловыйНачальныйОбразНаСервере(Параметры, АдресХранилища) Экспорт
Попытка
СтрокаСоединения = "File=""" + Параметры.ИмяКаталога + """;"
+ "Locale=""" + Параметры.Язык + """;";
ПланыОбмена.СоздатьНачальныйОбраз(Параметры.Узел, СтрокаСоединения); // Собственно создание начального образа.
Если Параметры.ЕстьФайлыВТомах Тогда
ZipФайл = Новый ЗаписьZipФайла;
ZipФайл.Открыть(Параметры.ПутьКАрхивуСФайламиТомов);
ВременныеФайлы = Новый Массив;
ВременныеФайлы = НайтиФайлы(Параметры.ИмяКаталогаФайлов, ПолучитьМаскуВсеФайлы());
Для Каждого ВременныйФайл Из ВременныеФайлы Цикл
Если ВременныйФайл.ЭтоФайл() Тогда
ПутьВременногоФайла = ВременныйФайл.ПолноеИмя;
ZipФайл.Добавить(ПутьВременногоФайла);
КонецЕсли;
КонецЦикла;
ZipФайл.Записать();
УдалитьФайлы(Параметры.ИмяКаталогаФайлов); // Удаляем вместе с файлами внутри.
КонецЕсли;
Исключение
УдалитьФайлы(Параметры.ИмяКаталога);
ВызватьИсключение;
КонецПопытки;
ПутьВременногоФайлаБазы = Параметры.ИмяКаталога + "\1Cv8.1CD";
ПереместитьФайл(ПутьВременногоФайлаБазы, Параметры.ПолноеИмяФайловойБазы);
// очистка
УдалитьФайлы(Параметры.ИмяКаталога);
КонецПроцедуры
// Подготовка параметров и предварительные проверки перед созданием серверного начального образа.
//
Функция ПодготовитьДанныеДляСозданияСерверногоНачальногоОбраза(СтруктураПараметров) Экспорт
Результат = Новый Структура("ДанныеПодготовлены, ТребуетсяПодтверждение, ТекстВопроса", Истина, Ложь, "");
ПутьКАрхивуСФайламиТомовWindows = СтруктураПараметров.ПутьКАрхивуСФайламиТомовWindows;
ПутьКАрхивуСФайламиТомовLinux = СтруктураПараметров.ПутьКАрхивуСФайламиТомовLinux;
ПутьКАрхивуСФайламиТомов = "";
ЕстьФайлыВТомах = Ложь;
Если РаботаСФайлами.ЕстьТомаХраненияФайлов() Тогда
ЕстьФайлыВТомах = ЕстьФайлыВТомах();
КонецЕсли;
Если ОбщегоНазначения.ЭтоWindowsСервер() Тогда
ПутьКАрхивуСФайламиТомов = ПутьКАрхивуСФайламиТомовWindows;
Если ЕстьФайлыВТомах Тогда
Если Не ПустаяСтрока(ПутьКАрхивуСФайламиТомов)
И (Лев(ПутьКАрхивуСФайламиТомов, 2) <> "\\"
ИЛИ СтрНайти(ПутьКАрхивуСФайламиТомов, ":") <> 0) Тогда
ОбщегоНазначения.СообщитьПользователю(
НСтр("ru = 'Путь к архиву с файлами томов должен быть
|в формате UNC (\\servername\resource).'"),
,
"ПутьКАрхивуСФайламиТомовWindows");
Результат.ДанныеПодготовлены = Ложь;
КонецЕсли;
КонецЕсли;
Иначе
ПутьКАрхивуСФайламиТомов = ПутьКАрхивуСФайламиТомовLinux;
КонецЕсли;
Если Результат.ДанныеПодготовлены Тогда
Если ЕстьФайлыВТомах И ПустаяСтрока(ПутьКАрхивуСФайламиТомов) Тогда
ОбщегоНазначения.СообщитьПользователю(
НСтр("ru = 'Укажите полное имя архива с файлами томов (файл *.zip)'"),
,
"ПутьКАрхивуСФайламиТомовWindows");
Результат.ДанныеПодготовлены = Ложь;
Иначе
Если ЕстьФайлыВТомах Тогда
Файл = Новый Файл(ПутьКАрхивуСФайламиТомов);
Если Файл.Существует() Тогда
Результат.ТекстВопроса = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Файл ""%1"" уже существует.
|Заменить существующий файл?'"), ПутьКАрхивуСФайламиТомов);
Результат.ТребуетсяПодтверждение = Истина;
КонецЕсли;
КонецЕсли;
// Создать временный каталог.
ИмяКаталога = ПолучитьИмяВременногоФайла();
СоздатьКаталог(ИмяКаталога);
// Создать временный каталог для файлов.
ИмяКаталогаФайлов = ПолучитьИмяВременногоФайла();
СоздатьКаталог(ИмяКаталогаФайлов);
// Для передачи пути каталога файлов в обработчик ПриОтправкеДанныхФайла.
СохранитьНастройку("ОбменФайлами", "ВременныйКаталог", ИмяКаталогаФайлов);
// Добавляем в параметры переменные, которые потребуются для создания начального образа.
СтруктураПараметров.Вставить("ЕстьФайлыВТомах", ЕстьФайлыВТомах);
СтруктураПараметров.Вставить("ПутьФайла", ПутьКАрхивуСФайламиТомов);
СтруктураПараметров.Вставить("ИмяКаталога", ИмяКаталога);
СтруктураПараметров.Вставить("ИмяКаталогаФайлов", ИмяКаталогаФайлов);
КонецЕсли;
КонецЕсли;
Возврат Результат;
КонецФункции
// Создать серверный начальный образ на сервере.
//
Процедура СоздатьСерверныйНачальныйОбразНаСервере(Параметры, АдресРезультата) Экспорт
Попытка
ПланыОбмена.СоздатьНачальныйОбраз(Параметры.Узел, Параметры.СтрокаСоединения);
Если Параметры.ЕстьФайлыВТомах Тогда
ZipФайл = Новый ЗаписьZipФайла;
ПутьZIP = Параметры.ПутьФайла;
ZipФайл.Открыть(ПутьZIP);
ВременныеФайлы = Новый Массив;
ВременныеФайлы = НайтиФайлы(Параметры.ИмяКаталогаФайлов, ПолучитьМаскуВсеФайлы());
Для Каждого ВременныйФайл Из ВременныеФайлы Цикл
Если ВременныйФайл.ЭтоФайл() Тогда
ПутьВременногоФайла = ВременныйФайл.ПолноеИмя;
ZipФайл.Добавить(ПутьВременногоФайла);
КонецЕсли;
КонецЦикла;
ZipФайл.Записать();
УдалитьФайлы(Параметры.ИмяКаталогаФайлов); // Удаляем вместе с файлами внутри.
КонецЕсли;
Исключение
УдалитьФайлы(Параметры.ИмяКаталога);
ВызватьИсключение;
КонецПопытки;
// очистка
УдалитьФайлы(Параметры.ИмяКаталога);
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиРегламентныхЗаданий
// Обработчик регламентного задания ИзвлечениеТекста.
// Извлекает текст из файлов на диске.
//
Процедура ИзвлечьТекстИзФайловНаСервере() Экспорт
ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(Метаданные.РегламентныеЗадания.ИзвлечениеТекста);
ИзвлечьТекстИзФайлов();
КонецПроцедуры
#КонецОбласти
#Область ИзвлечениеТекста
// Возвращает текст запроса для получения файлов у которых не извлечен текст.
//
// Параметры:
// ПолучитьВсеФайлы - Булево - начальное значение Ложь. Позволяет отключить выборку
// файлов по частям, если передать Истина.
//
// Возвращаемое значение:
// Строка - текст запроса.
//
Функция ТекстЗапросаДляИзвлеченияТекста(ПолучитьВсеФайлы = Ложь, ДополнительныеПоля = Ложь) Экспорт
// Текст запроса формируется по всем справочникам присоединенных файлов.
ТекстЗапроса = "";
ТипыФайлов = Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип.Типы();
ВсеИменаСправочников = Новый Массив;
Для Каждого Тип Из ТипыФайлов Цикл
МетаданныеСправочникаФайлов = Метаданные.НайтиПоТипу(Тип);
НеИспользоватьПолнотекстовыйПоиск = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.НеИспользовать;
Если МетаданныеСправочникаФайлов.ПолнотекстовыйПоиск = НеИспользоватьПолнотекстовыйПоиск Тогда
Продолжить;
КонецЕсли;
ВсеИменаСправочников.Добавить(МетаданныеСправочникаФайлов.Имя);
КонецЦикла;
ЧислоФайловВВыборке = Цел(100 / ВсеИменаСправочников.Количество());
ЧислоФайловВВыборке = ?(ЧислоФайловВВыборке < 10, 10, ЧислоФайловВВыборке);
Для каждого ИмяСправочника Из ВсеИменаСправочников Цикл
Если НЕ ПустаяСтрока(ТекстЗапроса) Тогда
ТекстЗапроса = ТекстЗапроса + "
|
|ОБЪЕДИНИТЬ ВСЕ
|
|";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + ТекстЗапросаДляФайловСНеизвлеченнымТекстом(ИмяСправочника,
ЧислоФайловВВыборке, ПолучитьВсеФайлы, ДополнительныеПоля);
КонецЦикла;
Возврат ТекстЗапроса;
КонецФункции
#КонецОбласти
#Область Сканирование
Функция ПараметрыСканераВПеречисления(РазрешениеЧисло, ЦветностьЧисло, ПоворотЧисло, РазмерБумагиЧисло) Экспорт
Если РазрешениеЧисло = 200 Тогда
Разрешение = Перечисления.РазрешенияСканированногоИзображения.dpi200;
ИначеЕсли РазрешениеЧисло = 300 Тогда
Разрешение = Перечисления.РазрешенияСканированногоИзображения.dpi300;
ИначеЕсли РазрешениеЧисло = 600 Тогда
Разрешение = Перечисления.РазрешенияСканированногоИзображения.dpi600;
ИначеЕсли РазрешениеЧисло = 1200 Тогда
Разрешение = Перечисления.РазрешенияСканированногоИзображения.dpi1200;
КонецЕсли;
Если ЦветностьЧисло = 0 Тогда
Цветность = Перечисления.ЦветностиИзображения.Монохромное;
ИначеЕсли ЦветностьЧисло = 1 Тогда
Цветность = Перечисления.ЦветностиИзображения.ГрадацииСерого;
ИначеЕсли ЦветностьЧисло = 2 Тогда
Цветность = Перечисления.ЦветностиИзображения.Цветное;
КонецЕсли;
Если ПоворотЧисло = 0 Тогда
Поворот = Перечисления.СпособыПоворотаИзображения.НетПоворота;
ИначеЕсли ПоворотЧисло = 90 Тогда
Поворот = Перечисления.СпособыПоворотаИзображения.ВправоНа90;
ИначеЕсли ПоворотЧисло = 180 Тогда
Поворот = Перечисления.СпособыПоворотаИзображения.ВправоНа180;
ИначеЕсли ПоворотЧисло = 270 Тогда
Поворот = Перечисления.СпособыПоворотаИзображения.ВлевоНа90;
КонецЕсли;
Если РазмерБумагиЧисло = 0 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.НеЗадано;
ИначеЕсли РазмерБумагиЧисло = 11 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.A3;
ИначеЕсли РазмерБумагиЧисло = 1 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.A4;
ИначеЕсли РазмерБумагиЧисло = 5 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.A5;
ИначеЕсли РазмерБумагиЧисло = 6 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.B4;
ИначеЕсли РазмерБумагиЧисло = 2 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.B5;
ИначеЕсли РазмерБумагиЧисло = 7 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.B6;
ИначеЕсли РазмерБумагиЧисло = 14 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.C4;
ИначеЕсли РазмерБумагиЧисло = 15 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.C5;
ИначеЕсли РазмерБумагиЧисло = 16 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.C6;
ИначеЕсли РазмерБумагиЧисло = 3 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.USLetter;
ИначеЕсли РазмерБумагиЧисло = 4 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.USLegal;
ИначеЕсли РазмерБумагиЧисло = 10 Тогда
РазмерБумаги = Перечисления.РазмерыБумаги.USExecutive;
КонецЕсли;
Результат = Новый Структура;
Результат.Вставить("Разрешение", Разрешение);
Результат.Вставить("Цветность", Цветность);
Результат.Вставить("Поворот", Поворот);
Результат.Вставить("РазмерБумаги", РазмерБумаги);
Возврат Результат;
КонецФункции
#КонецОбласти
#Область ОчисткаНенужныхФайлов
Процедура ОчиститьНенужныеФайлы(Параметры = Неопределено, АдресРезультата = Неопределено) Экспорт
ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(Метаданные.РегламентныеЗадания.ОчисткаНенужныхФайлов);
УстановитьПривилегированныйРежим(Истина);
НастройкиОчистки = РегистрыСведений.НастройкиОчисткиФайлов.ТекущиеНастройкиОчистки();
НастройкиОчисткиФайлов = НастройкиОчистки.НайтиСтроки(Новый Структура("ЭтоНастройкаДляЭлементаСправочника", Ложь));
Для Каждого Настройка Из НастройкиОчисткиФайлов Цикл
МассивИсключений = Новый Массив;
ДетализированныеНастройки = НастройкиОчистки.НайтиСтроки(Новый Структура(
"ИдентификаторВладельца, ЭтоНастройкаДляЭлементаСправочника",
Настройка.ВладелецФайла,
Истина));
Если ДетализированныеНастройки.Количество() > 0 Тогда
Для Каждого ЭлементИсключение Из ДетализированныеНастройки Цикл
МассивИсключений.Добавить(ЭлементИсключение.ВладелецФайла);
ОчиститьДанныеНенужныхФайлов(ЭлементИсключение);
КонецЦикла;
КонецЕсли;
ОчиститьДанныеНенужныхФайлов(Настройка, МассивИсключений);
КонецЦикла;
КонецПроцедуры
Функция ОбъектыИсключенияПриОчисткеФайлов() Экспорт
Возврат НастройкиФайлов().НеОчищатьФайлы;
КонецФункции
#КонецОбласти
#Область ОбработчикиСобытийПодсистемКонфигурации
// См. СтандартныеПодсистемыСервер.ПриОтправкеДанныхПодчиненному.
Процедура ПриОтправкеДанныхПодчиненному(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза, Получатель) Экспорт
ПриОтправкеФайла(ЭлементДанных, ОтправкаЭлемента, СозданиеНачальногоОбраза, Получатель);
КонецПроцедуры
// См. СтандартныеПодсистемыСервер.ПриОтправкеДанныхГлавному.
Процедура ПриОтправкеДанныхГлавному(ЭлементДанных, ОтправкаЭлемента, Получатель) Экспорт
ПриОтправкеФайла(ЭлементДанных, ОтправкаЭлемента);
КонецПроцедуры
// См. СтандартныеПодсистемыСервер.ПриПолученииДанныхОтПодчиненного.
Процедура ПриПолученииДанныхОтПодчиненного(ЭлементДанных, ПолучениеЭлемента, ОтправкаНазад, Отправитель) Экспорт
ПриПолученииФайла(ЭлементДанных, ПолучениеЭлемента, Отправитель);
КонецПроцедуры
// См. СтандартныеПодсистемыСервер.ПриПолученииДанныхОтГлавного.
Процедура ПриПолученииДанныхОтГлавного(ЭлементДанных, ПолучениеЭлемента, ОтправкаНазад, Отправитель) Экспорт
ПриПолученииФайла(ЭлементДанных, ПолучениеЭлемента);
КонецПроцедуры
// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииИсключенийПоискаСсылок.
Процедура ПриДобавленииИсключенийПоискаСсылок(ИсключенияПоискаСсылок) Экспорт
ИсключенияПоискаСсылок.Добавить(Метаданные.РегистрыСведений.ФайлыВРабочемКаталоге.ПолноеИмя());
ИсключенияПоискаСсылок.Добавить(Метаданные.РегистрыСведений.СведенияОФайлах.ПолноеИмя());
ИсключенияПоискаСсылок.Добавить("Справочник.Файлы.Реквизиты.ТекущаяВерсия");
КонецПроцедуры
// Параметры:
// ТекущиеДела - см. ТекущиеДелаСервер.ТекущиеДела.
//
Процедура ПриЗаполненииСпискаТекущихДел(ТекущиеДела) Экспорт
МодульТекущиеДелаСервер = ОбщегоНазначения.ОбщийМодуль("ТекущиеДелаСервер");
Если Не ПравоДоступа("Чтение", Метаданные.Справочники.Файлы)
Или МодульТекущиеДелаСервер.ДелоОтключено("РедактируемыеФайлы") Тогда
Возврат;
КонецЕсли;
КоличествоЗанятыхФайлов = КоличествоЗанятыхФайлов();
// Процедура вызывается только при наличии подсистемы "Текущие дела", поэтому здесь
// не делается проверка существования подсистемы.
Разделы = МодульТекущиеДелаСервер.РазделыДляОбъекта(Метаданные.Справочники.Файлы.ПолноеИмя());
Для Каждого Раздел Из Разделы Цикл
ИдентификаторРедактируемыеФайлы = "РедактируемыеФайлы" + СтрЗаменить(Раздел.ПолноеИмя(), ".", "");
Дело = ТекущиеДела.Добавить();
Дело.Идентификатор = ИдентификаторРедактируемыеФайлы;
Дело.ЕстьДела = КоличествоЗанятыхФайлов > 0;
Дело.Представление = НСтр("ru = 'Редактируемые файлы'");
Дело.Количество = КоличествоЗанятыхФайлов;
Дело.Важное = Ложь;
Дело.Форма = "Обработка.РаботаСФайлами.Форма.РедактируемыеФайлы";
Дело.Владелец = Раздел;
КонецЦикла;
КонецПроцедуры
// См. ГрупповоеИзменениеОбъектовПереопределяемый.ПриОпределенииОбъектовСРедактируемымиРеквизитами.
Процедура ПриОпределенииОбъектовСРедактируемымиРеквизитами(Объекты) Экспорт
Объекты.Вставить(Метаданные.Справочники.ПапкиФайлов.ПолноеИмя(), "РеквизитыРедактируемыеВГрупповойОбработке");
Объекты.Вставить(Метаданные.Справочники.Файлы.ПолноеИмя(), "РеквизитыРедактируемыеВГрупповойОбработке");
Объекты.Вставить(Метаданные.Справочники.ВерсииФайлов.ПолноеИмя(), "РеквизитыРедактируемыеВГрупповойОбработке");
Объекты.Вставить(Метаданные.Справочники.ТомаХраненияФайлов.ПолноеИмя(), "РеквизитыРедактируемыеВГрупповойОбработке");
КонецПроцедуры
// См. ЗагрузкаДанныхИзФайлаПереопределяемый.ПриОпределенииСправочниковДляЗагрузкиДанных.
Процедура ПриОпределенииСправочниковДляЗагрузкиДанных(ЗагружаемыеСправочники) Экспорт
// Синхронизация файлов с облачным сервисом.
// Загрузка в справочник ТомаХраненияФайлов запрещена.
СтрокаТаблицы = ЗагружаемыеСправочники.Найти(Метаданные.Справочники.ТомаХраненияФайлов.ПолноеИмя(), "ПолноеИмя");
Если СтрокаТаблицы <> Неопределено Тогда
ЗагружаемыеСправочники.Удалить(СтрокаТаблицы);
КонецЕсли;
КонецПроцедуры
// См. РегламентныеЗаданияПереопределяемый.ПриОпределенииНастроекРегламентныхЗаданий.
//
// Параметры:
// Зависимости- см. РегламентныеЗаданияПереопределяемый.ПриОпределенииНастроекРегламентныхЗаданий.Настройки
//
Процедура ПриОпределенииНастроекРегламентныхЗаданий(Зависимости) Экспорт
Зависимость = Зависимости.Добавить();
Зависимость.РегламентноеЗадание = Метаданные.РегламентныеЗадания.ИзвлечениеТекста;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ПолнотекстовыйПоиск") Тогда
МодульПолнотекстовыйПоискСервер = ОбщегоНазначения.ОбщийМодуль("ПолнотекстовыйПоискСервер");
Зависимость.ФункциональнаяОпция = МодульПолнотекстовыйПоискСервер.ФункциональнаяОпцияИспользоватьПолнотекстовыйПоиск();
КонецЕсли;
Зависимость.ДоступноВМоделиСервиса = Ложь;
Зависимость = Зависимости.Добавить();
Зависимость.РегламентноеЗадание = Метаданные.РегламентныеЗадания.ОчисткаНенужныхФайлов;
Зависимость.РаботаетСВнешнимиРесурсами = Истина;
Зависимость = Зависимости.Добавить();
Зависимость.РегламентноеЗадание = Метаданные.РегламентныеЗадания.СинхронизацияФайлов;
Зависимость.ФункциональнаяОпция = Метаданные.ФункциональныеОпции.ИспользоватьСинхронизациюФайлов;
Зависимость.РаботаетСВнешнимиРесурсами = Истина;
КонецПроцедуры
// См. УправлениеДоступомПереопределяемый.ПриЗаполненииСписковСОграничениемДоступа.
Процедура ПриЗаполненииСписковСОграничениемДоступа(Списки) Экспорт
Списки.Вставить(Метаданные.Справочники.ВерсииФайлов, Истина);
Списки.Вставить(Метаданные.Справочники.ПапкиФайлов, Истина);
Списки.Вставить(Метаданные.Справочники.Файлы, Истина);
КонецПроцедуры
// См. УправлениеДоступомПереопределяемый.ПриЗаполненииВозможныхПравДляНастройкиПравОбъектов.
Процедура ПриЗаполненииВозможныхПравДляНастройкиПравОбъектов(ВозможныеПрава) Экспорт
////////////////////////////////////////////////////////////
// Справочник.ПапкиФайлов
// Право "Чтение папок и файлов".
Право = ВозможныеПрава.Добавить();
Право.ВладелецПрав = Метаданные.Справочники.ПапкиФайлов.ПолноеИмя();
Право.Имя = "Чтение";
Право.Заголовок = НСтр("ru = 'Чтение'");
Право.Подсказка = НСтр("ru = 'Чтение папок и файлов'");
Право.НачальноеЗначение = Истина;
// Права для стандартных шаблонов ограничений доступа.
Право.ЧтениеВТаблицах.Добавить("*");
// Право "Изменение папок"
Право = ВозможныеПрава.Добавить();
Право.ВладелецПрав = Метаданные.Справочники.ПапкиФайлов.ПолноеИмя();
Право.Имя = "ИзменениеПапок";
Право.Заголовок = НСтр("ru = 'Изменение
|папок'");
Право.Подсказка = НСтр("ru = 'Добавление, изменение и
|пометка удаления папок файлов'");
// Права, требуемые для этого права.
Право.ТребуемыеПрава.Добавить("Чтение");
// Права для стандартных шаблонов ограничений доступа.
Право.ИзменениеВТаблицах.Добавить(Метаданные.Справочники.ПапкиФайлов.ПолноеИмя());
// Право "Изменение файлов"
Право = ВозможныеПрава.Добавить();
Право.ВладелецПрав = Метаданные.Справочники.ПапкиФайлов.ПолноеИмя();
Право.Имя = "ИзменениеФайлов";
Право.Заголовок = НСтр("ru = 'Изменение
|файлов'");
Право.Подсказка = НСтр("ru = 'Изменение файлов в папке'");
// Права, требуемые для этого права.
Право.ТребуемыеПрава.Добавить("Чтение");
// Права для стандартных шаблонов ограничений доступа.
Право.ИзменениеВТаблицах.Добавить("*");
// Право "Добавление файлов"
Право = ВозможныеПрава.Добавить();
Право.ВладелецПрав = Метаданные.Справочники.ПапкиФайлов.ПолноеИмя();
Право.Имя = "ДобавлениеФайлов";
Право.Заголовок = НСтр("ru = 'Добавление
|файлов'");
Право.Подсказка = НСтр("ru = 'Добавление файлов в папку'");
// Права, требуемые для этого права.
Право.ТребуемыеПрава.Добавить("ИзменениеФайлов");
// Право "Пометка удаления файлов".
Право = ВозможныеПрава.Добавить();
Право.ВладелецПрав = Метаданные.Справочники.ПапкиФайлов.ПолноеИмя();
Право.Имя = "ПометкаУдаленияФайлов";
Право.Заголовок = НСтр("ru = 'Пометка
|удаления'");
Право.Подсказка = НСтр("ru = 'Пометка удаления файлов в папке'");
// Права, требуемые для этого права.
Право.ТребуемыеПрава.Добавить("ИзменениеФайлов");
Право = ВозможныеПрава.Добавить();
Право.ВладелецПрав = Метаданные.Справочники.ПапкиФайлов.ПолноеИмя();
Право.Имя = "УправлениеПравами";
Право.Заголовок = НСтр("ru = 'Управление
|правами'");
Право.Подсказка = НСтр("ru = 'Управление правами папки'");
// Права, требуемые для этого права.
Право.ТребуемыеПрава.Добавить("Чтение");
КонецПроцедуры
// См. УправлениеДоступомПереопределяемый.ПриЗаполненииВидовОграниченийПравОбъектовМетаданных.
Процедура ПриЗаполненииВидовОграниченийПравОбъектовМетаданных(Описание) Экспорт
Описание = Описание + "
|Справочник.ПапкиФайлов.Чтение.НастройкиПрав.Справочник.ПапкиФайлов
|Справочник.ПапкиФайлов.Изменение.НастройкиПрав.Справочник.ПапкиФайлов
|Справочник.Файлы.Чтение.НастройкиПрав.Справочник.ПапкиФайлов
|Справочник.Файлы.Изменение.НастройкиПрав.Справочник.ПапкиФайлов
|Справочник.Файлы.Изменение.ВнешниеПользователи
|Справочник.Файлы.Чтение.ВнешниеПользователи
|";
ТипыВладельцевФайлов = Метаданные.ОпределяемыеТипы.ВладелецФайлов.Тип.Типы();
Для Каждого ТипВладельца Из ТипыВладельцевФайлов Цикл
МетаданныеВладельца = Метаданные.НайтиПоТипу(ТипВладельца);
Если МетаданныеВладельца = Неопределено Тогда
Продолжить;
КонецЕсли;
ПолноеИмяВладельца = МетаданныеВладельца.ПолноеИмя();
Описание = Описание + "
|Справочник.ВерсииФайлов.Чтение.Объект." + ПолноеИмяВладельца + "
|Справочник.ВерсииФайлов.Изменение.Объект." + ПолноеИмяВладельца + "
|Справочник.Файлы.Чтение.Объект." + ПолноеИмяВладельца + "
|Справочник.Файлы.Изменение.Объект." + ПолноеИмяВладельца + "
|";
КонецЦикла;
КонецПроцедуры
// См. ОбновлениеИнформационнойБазыБСП.ПриДобавленииОбработчиковОбновления.
Процедура ПриДобавленииОбработчиковОбновления(Обработчики) Экспорт
Обработчик = Обработчики.Добавить();
Обработчик.Версия = "2.4.1.1";
Обработчик.ОбщиеДанные = Истина;
Обработчик.НачальноеЗаполнение = Истина;
Обработчик.Процедура = "РаботаСФайламиСлужебный.ОбновитьСписокЗапрещенныхРасширений";
Обработчик.РежимВыполнения = "Оперативно";
Обработчик = Обработчики.Добавить();
Обработчик.Версия = "2.4.1.1";
Обработчик.НачальноеЗаполнение = Истина;
Обработчик.Процедура = "РаботаСФайламиСлужебный.ОбновитьСписокЗапрещенныхРасширенийВОбластиДанных";
Обработчик.РежимВыполнения = "Оперативно";
Обработчик = Обработчики.Добавить();
Обработчик.Версия = "3.1.3.119";
Обработчик.ОбщиеДанные = Истина;
Обработчик.НачальноеЗаполнение = Истина;
Обработчик.Процедура = "РаботаСФайламиСлужебный.ОбновитьСписокРасширенийТекстовыхФайлов";
Обработчик.РежимВыполнения = "Оперативно";
ПодсистемаЭПСуществует = ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись");
Если ПодсистемаЭПСуществует Тогда
Обработчик = Обработчики.Добавить();
Обработчик.Версия = "2.4.1.49";
Обработчик.Комментарий =
НСтр("ru = 'Перенос электронных подписей и сертификатов шифрования
|из табличных частей в регистры сведений.'");
Обработчик.Идентификатор = Новый УникальныйИдентификатор("d70f378a-41f5-4b0a-a1a7-f4ba27c7f91b");
Обработчик.Процедура = "РаботаСФайлами.ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведений";
Обработчик.РежимВыполнения = "Отложенно";
Обработчик.ОчередьОтложеннойОбработки = 1;
Обработчик.ПроцедураЗаполненияДанныхОбновления = "РаботаСФайламиСлужебный.ЗарегистрироватьОбъектыДляПереносаЭлектронныхПодписейИСертификатовШифрования";
Обработчик.ЧитаемыеОбъекты = СтрСоединить(ПолныеИменаСправочниковПрисоединенныхФайлов(), ", ");
Обработчик.ИзменяемыеОбъекты = ИзменяемыеОбъектыПриПереносеЭлектронныхПодписейИСертификатовШифрования() + "," + СтрСоединить(ПолныеИменаСправочниковПрисоединенныхФайлов(), ", ");
Обработчик.ПроцедураПроверки = "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы";
Обработчик.ПриоритетыВыполнения = ОбновлениеИнформационнойБазы.ПриоритетыВыполненияОбработчика();
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "РегистрыСведений.ДвоичныеДанныеФайлов.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Приоритет.Порядок = "До";
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "РегистрыСведений.НаличиеФайлов.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Приоритет.Порядок = "Любой";
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "РегистрыСведений.СведенияОФайлах.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Приоритет.Порядок = "Любой";
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "Справочники.Файлы.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Приоритет.Порядок = "Любой";
КонецЕсли;
Обработчик = Обработчики.Добавить();
Обработчик.Версия = "2.4.1.1";
Обработчик.Комментарий =
НСтр("ru = 'Перенос информации о наличии файлов в регистр сведений Наличие файлов.'");
Обработчик.Идентификатор = Новый УникальныйИдентификатор("a84931bb-dfd5-4525-ab4a-1a0646e17334");
Обработчик.Процедура = "РегистрыСведений.НаличиеФайлов.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Обработчик.РежимВыполнения = "Отложенно";
Обработчик.ПроцедураЗаполненияДанныхОбновления = "РегистрыСведений.НаличиеФайлов.ЗарегистрироватьДанныеКОбработкеДляПереходаНаНовуюВерсию";
Обработчик.ЧитаемыеОбъекты = "Справочник.Файлы";
Обработчик.ИзменяемыеОбъекты = "Справочник.Файлы,РегистрСведений.НаличиеФайлов";
Обработчик.БлокируемыеОбъекты = "Справочник.Файлы";
Обработчик.ОчередьОтложеннойОбработки = 3;
Обработчик.ПроцедураПроверки = "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы";
Обработчик.ПриоритетыВыполнения = ОбновлениеИнформационнойБазы.ПриоритетыВыполненияОбработчика();
Если ПодсистемаЭПСуществует Тогда
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "РаботаСФайлами.ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведений";
Приоритет.Порядок = "Любой";
КонецЕсли;
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "РегистрыСведений.СведенияОФайлах.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Приоритет.Порядок = "Любой";
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "Справочники.Файлы.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Приоритет.Порядок = "Любой";
Обработчик = Обработчики.Добавить();
Обработчик.Версия = "3.0.2.46";
Обработчик.Комментарий =
НСтр("ru = 'Обновление универсальной даты и типа хранения элементов справочника Файлы.'");
Обработчик.Идентификатор = Новый УникальныйИдентификатор("8b417c47-dd46-45ce-b59b-c675059c9020");
Обработчик.Процедура = "Справочники.Файлы.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Обработчик.РежимВыполнения = "Отложенно";
Обработчик.ЧитаемыеОбъекты = "Справочник.Файлы";
Обработчик.ИзменяемыеОбъекты = "Справочник.Файлы,РегистрСведений.СведенияОФайлах";
Обработчик.БлокируемыеОбъекты = "Справочник.Файлы,Справочник.ВерсииФайлов";
Обработчик.ОчередьОтложеннойОбработки = 5;
Обработчик.ПроцедураЗаполненияДанныхОбновления = "Справочники.Файлы.ЗарегистрироватьДанныеКОбработкеДляПереходаНаНовуюВерсию";
Обработчик.ПроцедураПроверки = "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы";
Обработчик.ПриоритетыВыполнения = ОбновлениеИнформационнойБазы.ПриоритетыВыполненияОбработчика();
Обработчик.Многопоточный = Истина;
Если ПодсистемаЭПСуществует Тогда
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "РаботаСФайлами.ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведений";
Приоритет.Порядок = "Любой";
КонецЕсли;
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "РегистрыСведений.НаличиеФайлов.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Приоритет.Порядок = "Любой";
Приоритет = Обработчик.ПриоритетыВыполнения.Добавить();
Приоритет.Процедура = "РегистрыСведений.СведенияОФайлах.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Приоритет.Порядок = "Любой";
Обработчик = Обработчики.Добавить();
Обработчик.Процедура = "РегистрыСведений.СведенияОФайлах.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Обработчик.Версия = "3.0.2.46";
Обработчик.РежимВыполнения = "Отложенно";
Обработчик.Идентификатор = Новый УникальныйИдентификатор("5137a43e-75aa-4a68-ba2f-525a3a646af8");
Обработчик.Многопоточный = Истина;
Обработчик.ОчередьОтложеннойОбработки = 4;
Обработчик.ПроцедураЗаполненияДанныхОбновления = "РегистрыСведений.СведенияОФайлах.ЗарегистрироватьДанныеКОбработкеДляПереходаНаНовуюВерсию";
Обработчик.ПроцедураПроверки = "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы";
Обработчик.Комментарий = НСтр("ru = 'Перенос информации о файлах в регистр сведений Сведения о файлах.'");
Читаемые = Новый Массив;
Читаемые.Добавить(Метаданные.Справочники.Файлы.ПолноеИмя());
Читаемые.Добавить(Метаданные.РегистрыСведений.СведенияОФайлах.ПолноеИмя());
Обработчик.ЧитаемыеОбъекты = СтрСоединить(Читаемые, ",");
Изменяемые = Новый Массив;
Изменяемые.Добавить(Метаданные.РегистрыСведений.СведенияОФайлах.ПолноеИмя());
Обработчик.ИзменяемыеОбъекты = СтрСоединить(Изменяемые, ",");
Блокируемые = Новый Массив;
Блокируемые.Добавить(Метаданные.Справочники.Файлы.ПолноеИмя());
Блокируемые.Добавить(Метаданные.РегистрыСведений.СведенияОФайлах.ПолноеИмя());
Обработчик.БлокируемыеОбъекты = СтрСоединить(Блокируемые, ",");
Обработчик.ПриоритетыВыполнения = ОбновлениеИнформационнойБазы.ПриоритетыВыполненияОбработчика();
Если ПодсистемаЭПСуществует Тогда
НоваяСтрока = Обработчик.ПриоритетыВыполнения.Добавить();
НоваяСтрока.Процедура = "РаботаСФайлами.ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведений";
НоваяСтрока.Порядок = "Любой";
КонецЕсли;
НоваяСтрока = Обработчик.ПриоритетыВыполнения.Добавить();
НоваяСтрока.Процедура = "РегистрыСведений.ДвоичныеДанныеФайлов.ОбработатьДанныеДляПереходаНаНовуюВерсию";
НоваяСтрока.Порядок = "До";
НоваяСтрока = Обработчик.ПриоритетыВыполнения.Добавить();
НоваяСтрока.Процедура = "РегистрыСведений.НаличиеФайлов.ОбработатьДанныеДляПереходаНаНовуюВерсию";
НоваяСтрока.Порядок = "Любой";
НоваяСтрока = Обработчик.ПриоритетыВыполнения.Добавить();
НоваяСтрока.Процедура = "Справочники.Файлы.ОбработатьДанныеДляПереходаНаНовуюВерсию";
НоваяСтрока.Порядок = "Любой";
Обработчик = Обработчики.Добавить();
Обработчик.Процедура = "РегистрыСведений.ДвоичныеДанныеФайлов.ОбработатьДанныеДляПереходаНаНовуюВерсию";
Обработчик.Версия = "3.1.3.260";
Обработчик.РежимВыполнения = "Отложенно";
Обработчик.ОчередьОтложеннойОбработки = 6;
Обработчик.Идентификатор = Новый УникальныйИдентификатор("84e58943-94fe-4f92-99b3-91be534d3754");
Обработчик.ПроцедураЗаполненияДанныхОбновления = "РегистрыСведений.ДвоичныеДанныеФайлов.ЗарегистрироватьДанныеКОбработкеДляПереходаНаНовуюВерсию";
Обработчик.ПроцедураПроверки = "ОбновлениеИнформационнойБазы.ДанныеОбновленыНаНовуюВерсиюПрограммы";
Обработчик.Комментарий = НСтр("ru = 'Создание недостающих версий файлов для элементов справочника Файлы.'");
Читаемые = Новый Массив;
Читаемые.Добавить(Метаданные.Справочники.Файлы.ПолноеИмя());
Читаемые.Добавить(Метаданные.РегистрыСведений.ДвоичныеДанныеФайлов.ПолноеИмя());
Обработчик.ЧитаемыеОбъекты = СтрСоединить(Читаемые, ",");
Изменяемые = Новый Массив;
Изменяемые.Добавить(Метаданные.Справочники.Файлы.ПолноеИмя());
Изменяемые.Добавить(Метаданные.РегистрыСведений.ДвоичныеДанныеФайлов.ПолноеИмя());
Изменяемые.Добавить(Метаданные.Справочники.ВерсииФайлов.ПолноеИмя());
Обработчик.ИзменяемыеОбъекты = СтрСоединить(Изменяемые, ",");
Блокируемые = Новый Массив;
Блокируемые.Добавить(Метаданные.РегистрыСведений.ДвоичныеДанныеФайлов.ПолноеИмя());
Блокируемые.Добавить(Метаданные.Справочники.ВерсииФайлов.ПолноеИмя());
Блокируемые.Добавить(Метаданные.Справочники.Файлы.ПолноеИмя());
Обработчик.БлокируемыеОбъекты = СтрСоединить(Блокируемые, ",");
Обработчик.ПриоритетыВыполнения = ОбновлениеИнформационнойБазы.ПриоритетыВыполненияОбработчика();
НоваяСтрока = Обработчик.ПриоритетыВыполнения.Добавить();
НоваяСтрока.Процедура = "РаботаСФайлами.ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведений";
НоваяСтрока.Порядок = "После";
НоваяСтрока = Обработчик.ПриоритетыВыполнения.Добавить();
НоваяСтрока.Процедура = "РегистрыСведений.НаличиеФайлов.ОбработатьДанныеДляПереходаНаНовуюВерсию";
НоваяСтрока.Порядок = "После";
НоваяСтрока = Обработчик.ПриоритетыВыполнения.Добавить();
НоваяСтрока.Процедура = "Справочники.Файлы.ОбработатьДанныеДляПереходаНаНовуюВерсию";
НоваяСтрока.Порядок = "После";
РаботаСФайламиВТомахСлужебный.ПриДобавленииОбработчиковОбновления(Обработчики);
КонецПроцедуры
// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииПереименованийОбъектовМетаданных.
Процедура ПриДобавленииПереименованийОбъектовМетаданных(Итог) Экспорт
Библиотека = "СтандартныеПодсистемы";
СтароеИмя = "Роль.РаботаСПапкамиФайлов";
НовоеИмя = "Роль.ДобавлениеИзменениеПапокИФайлов";
ОбщегоНазначения.ДобавитьПереименование(Итог, "2.4.1.1", СтароеИмя, НовоеИмя, Библиотека);
КонецПроцедуры
// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииПараметровРаботыКлиента.
Процедура ПриДобавленииПараметровРаботыКлиента(Параметры) Экспорт
Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
Возврат;
КонецЕсли;
НастройкиРаботыСФайлами = РаботаСФайламиСлужебныйПовтИсп.НастройкиРаботыСФайлами();
Параметры.Вставить("ПерсональныеНастройкиРаботыСФайлами", Новый ФиксированнаяСтруктура(
НастройкиРаботыСФайлами.ПерсональныеНастройки));
Параметры.Вставить("ОбщиеНастройкиРаботыСФайлами", Новый ФиксированнаяСтруктура(
НастройкиРаботыСФайлами.ОбщиеНастройки));
КонецПроцедуры
// См. ОбщегоНазначенияПереопределяемый.ПриДобавленииПараметровРаботыКлиентаПриЗапуске.
Процедура ПриДобавленииПараметровРаботыКлиентаПриЗапуске(Параметры) Экспорт
Если Не ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
Возврат;
КонецЕсли;
НастройкиРаботыСФайлами = РаботаСФайламиСлужебныйПовтИсп.НастройкиРаботыСФайлами();
Параметры.Вставить("ПерсональныеНастройкиРаботыСФайлами", Новый ФиксированнаяСтруктура(
НастройкиРаботыСФайлами.ПерсональныеНастройки));
КоличествоЗанятыхФайлов = 0;
Если ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
Пользователь = Пользователи.АвторизованныйПользователь();
Если ТипЗнч(Пользователь) = Тип("СправочникСсылка.Пользователи") Тогда
КоличествоЗанятыхФайлов = КоличествоЗанятыхФайлов();
КонецЕсли;
КонецЕсли;
Параметры.Вставить("КоличествоЗанятыхФайлов", КоличествоЗанятыхФайлов);
КонецПроцедуры
// См. РаботаВБезопасномРежимеПереопределяемый.ПриЗаполненииРазрешенийНаДоступКВнешнимРесурсам.
Процедура ПриЗаполненииРазрешенийНаДоступКВнешнимРесурсам(ЗапросыРазрешений) Экспорт
Если ПолучитьФункциональнуюОпцию("ХранитьФайлыВТомахНаДиске") Тогда
Справочники.ТомаХраненияФайлов.ДобавитьЗапросыНаИспользованиеВнешнихРесурсовВсехТомов(ЗапросыРазрешений);
КонецЕсли;
КонецПроцедуры
// См. ВыгрузкаЗагрузкаДанныхПереопределяемый.ПриЗаполненииТиповОбщихДанныхНеТребующихСопоставлениеСсылокПриЗагрузке.
Процедура ПриЗаполненииТиповОбщихДанныхНеТребующихСопоставлениеСсылокПриЗагрузке(Типы) Экспорт
// В процессе выгрузки данных ссылки на справочник ТомаХраненияФайлов очищаются,
// а при загрузке загрузка производится относительно настройки томов в ИБ, в которую
// производится загрузка, а не относительно настройки томов в ИБ, из которой были
// выгружены данные.
Типы.Добавить(Метаданные.Справочники.ТомаХраненияФайлов);
КонецПроцедуры
// См. ВариантыОтчетовПереопределяемый.НастроитьВариантыОтчетов.
Процедура ПриНастройкеВариантовОтчетов(Настройки) Экспорт
МодульВариантыОтчетов = ОбщегоНазначения.ОбщийМодуль("ВариантыОтчетов");
МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ОбъемНенужныхФайлов);
МодульВариантыОтчетов.НастроитьОтчетВМодулеМенеджера(Настройки, Метаданные.Отчеты.ПроверкаЦелостностиТома);
КонецПроцедуры
// См. ЦентрМониторингаПереопределяемый.ПриСбореПоказателейСтатистикиКонфигурации.
Процедура ПриСбореПоказателейСтатистикиКонфигурации() Экспорт
Если Не ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЦентрМониторинга") Тогда
Возврат;
КонецЕсли;
МодульЦентрМониторинга = ОбщегоНазначения.ОбщийМодуль("ЦентрМониторинга");
ТекстЗапроса =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(1) КАК Количество
|ИЗ
| Справочник.УчетныеЗаписиСинхронизацииФайлов КАК УчетныеЗаписиСинхронизацииФайлов";
Запрос = Новый Запрос(ТекстЗапроса);
Выборка = Запрос.Выполнить().Выбрать();
МодульЦентрМониторинга.ЗаписатьСтатистикуОбъектаКонфигурации("Справочник.УчетныеЗаписиСинхронизацииФайлов", Выборка.Количество());
КонецПроцедуры
// См. ПользователиПереопределяемый.ПриОпределенииНазначенияРолей
Процедура ПриОпределенииНазначенияРолей(НазначениеРолей) Экспорт
// СовместноДляПользователейИВнешнихПользователей.
НазначениеРолей.ТолькоДляВнешнихПользователей.Добавить(
Метаданные.Роли.ДобавлениеИзменениеПапокИФайловВнешнимиПользователями.Имя);
КонецПроцедуры
// См. УправлениеСвойствамиПереопределяемый.ПриПолученииПредопределенныхНаборовСвойств.
Процедура ПриПолученииПредопределенныхНаборовСвойств(Наборы) Экспорт
Набор = Наборы.Строки.Добавить();
Набор.Имя = "Справочник_ПапкиФайлов";
Набор.Идентификатор = Новый УникальныйИдентификатор("3f4bfd8d-b111-4416-8797-760b78f15910");
Набор = Наборы.Строки.Добавить();
Набор.Имя = "Справочник_Файлы";
Набор.Идентификатор = Новый УникальныйИдентификатор("f85ae5e1-0ff9-4c97-b2bb-d0996eacc6cf");
КонецПроцедуры
// Для перехода с версий БСП 2.3.7 и младше. Устанавливает связь между
// подсистемой ПрисоединенныеФайлы и РаботаСФайлами.
//
Процедура ПриОпределенииНаследованияПодсистем(Выгрузка, НаследующиеПодсистемы) Экспорт
ОтборПоУдаленным = Новый Структура;
ОтборПоУдаленным.Вставить("Обновлен", Истина);
ОтборПоУдаленным.Вставить("ПометкаУдаления", Истина);
Удаленные = Выгрузка.НайтиСтроки(ОтборПоУдаленным);
НаследующиеПодсистемы = Новый Массив;
Для Каждого Удаленный Из Удаленные Цикл
Если СтрНайти(Удаленный.ПолноеИмя, "Подсистема.СтандартныеПодсистемы.Подсистема.ПрисоединенныеФайлы") Тогда
СтрокаРаботаСФайлами = Выгрузка.Найти("Подсистема.СтандартныеПодсистемы.Подсистема.РаботаСФайлами", "ПолноеИмя");
Если СтрокаРаботаСФайлами <> Неопределено Тогда
НаследующиеПодсистемы.Добавить(СтрокаРаботаСФайлами);
КонецЕсли;
Прервать;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// См. ОбновлениеИнформационнойБазыПереопределяемый.ПриОпределенииНастроек
//
// Параметры:
// Объекты - Массив из ОбъектМетаданных
//
Процедура ПриОпределенииОбъектовСНачальнымЗаполнением(Объекты) Экспорт
Объекты.Добавить(Метаданные.Справочники.ПапкиФайлов);
КонецПроцедуры
#КонецОбласти
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
// Возвращает путь к рабочему каталогу пользователя в настройках.
//
// Возвращаемое значение:
// Строка - имя каталога.
//
Функция РабочийКаталогПользователя()
УстановитьПривилегированныйРежим(Истина);
ИмяКаталога = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("ЛокальныйКэшФайлов", "ПутьКЛокальномуКэшуФайлов");
Если ИмяКаталога = Неопределено Тогда
ИмяКаталога = "";
КонецЕсли;
Возврат ИмяКаталога;
КонецФункции
// Возвращает навигационную ссылку на файл (на реквизит или во временное хранилище).
//
// Параметры:
// ФайлСсылка - ОпределяемыйТип.ПрисоединенныйФайл
// УникальныйИдентификатор - УникальныйИдентификатор
//
// Возвращаемое значение:
// см. РаботаСФайламиСлужебныйВызовСервера.ПолучитьНавигационнуюСсылкуДляОткрытия
//
Функция НавигационнойСсылкиФайла(ФайлСсылка, УникальныйИдентификатор) Экспорт
Если ЭтоЭлементРаботаСФайлами(ФайлСсылка) Тогда
Возврат РаботаСФайламиСлужебныйВызовСервера.ПолучитьНавигационнуюСсылкуДляОткрытия(ФайлСсылка, УникальныйИдентификатор);
КонецЕсли;
Возврат Неопределено;
КонецФункции
// Обработчик подписки "при записи" присоединенного файла.
//
Процедура ПриЗаписиПрисоединенногоФайлаСервер(ВладелецФайлов, Источник) Экспорт
УстановитьПривилегированныйРежим(Истина);
НачатьТранзакцию();
Попытка
ЗаписьИзменилась = Ложь;
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.РегистрыСведений.НаличиеФайлов.ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("ОбъектСФайлами", ВладелецФайлов);
БлокировкаДанных.Заблокировать();
МенеджерЗаписи = РегистрыСведений.НаличиеФайлов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ОбъектСФайлами = ВладелецФайлов;
МенеджерЗаписи.Прочитать();
Если НЕ ЗначениеЗаполнено(МенеджерЗаписи.ОбъектСФайлами) Тогда
МенеджерЗаписи.ОбъектСФайлами = ВладелецФайлов;
ЗаписьИзменилась = Истина;
КонецЕсли;
Если НЕ МенеджерЗаписи.ЕстьФайлы Тогда
МенеджерЗаписи.ЕстьФайлы = Истина;
ЗаписьИзменилась = Истина;
КонецЕсли;
Если ПустаяСтрока(МенеджерЗаписи.ИдентификаторОбъекта) Тогда
МенеджерЗаписи.ИдентификаторОбъекта = ПолучитьОчереднойИдентификаторОбъекта();
ЗаписьИзменилась = Истина;
КонецЕсли;
Если ЗаписьИзменилась Тогда
МенеджерЗаписи.Записать();
КонецЕсли;
Если Не Источник.ЭтоГруппа Тогда
МенеджерЗаписи = РегистрыСведений.СведенияОФайлах.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Источник);
МенеджерЗаписи.Файл = Источник;
Если Источник.ПодписанЭП И Источник.Зашифрован Тогда
МенеджерЗаписи.НомерКартинкиПодписанЗашифрован = 2;
ИначеЕсли Источник.Зашифрован Тогда
МенеджерЗаписи.НомерКартинкиПодписанЗашифрован = 1;
ИначеЕсли Источник.ПодписанЭП Тогда
МенеджерЗаписи.НомерКартинкиПодписанЗашифрован = 0;
Иначе
МенеджерЗаписи.НомерКартинкиПодписанЗашифрован = -1;
КонецЕсли;
МенеджерЗаписи.Записать();
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Процедура ВыполнитьОчисткуДанныхОВерсии(ФайлСсылка)
ИмяФайлаСПутем = "";
ИмяФайлаСПутемДляУдаления = "";
НачатьТранзакцию();
Попытка
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка)).ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлСсылка);
БлокировкаДанных.Заблокировать();
ФайлОбъект = ФайлСсылка.ПолучитьОбъект();
ТекстКомментария = НСтр("ru = 'Файл удален при очистке ненужных файлов.'")
+ " " + Формат(ТекущаяДатаСеанса(),"ДЛФ=D") + Символы.ПС;
Если ФайлОбъект.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
РаботаСФайламиВТомахСлужебный.УдалитьДанныеФайла(ФайлОбъект, ТекстКомментария);
Иначе
УстановитьПривилегированныйРежим(Истина);
НаборЗаписей = РегистрыСведений.ДвоичныеДанныеФайлов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Файл.Установить(ФайлСсылка);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() > 0 Тогда
ФайлОбъект.Комментарий = ТекстКомментария + ФайлОбъект.Комментарий;
ФайлОбъект.Записать();
НаборЗаписей.Очистить();
НаборЗаписей.Записать();
КонецЕсли;
ФайлОбъект.УстановитьПометкуУдаления(Истина);
УстановитьПривилегированныйРежим(Ложь);
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Если Не ПустаяСтрока(ИмяФайлаСПутем) Тогда
// Записать ошибку в журнал регистрации.
ЗаписьЖурналаРегистрации(НСтр("ru = 'Очистка ненужных файлов'", ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка,, ФайлСсылка, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
// Вернем файл на прежнее место в случае ошибки.
ПереместитьФайл(ИмяФайлаСПутемДляУдаления, ИмяФайлаСПутем);
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Процедура ВыполнитьОчисткуДанныхОФайле(ФайлСсылка)
ИмяФайлаСПутем = "";
ИмяФайлаСПутемДляУдаления = "";
НачатьТранзакцию();
Попытка
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка)).ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлСсылка);
БлокировкаДанных.Заблокировать();
ФайлОбъект = ФайлСсылка.ПолучитьОбъект(); // ОпределяемыйТип.ПрисоединенныйФайлОбъект
ТекстОписания = НСтр("ru = 'Файл удален при очистке ненужных файлов.'")
+ " " + Формат(ТекущаяДатаСеанса(),"ДЛФ=D") + Символы.ПС;
Если ФайлОбъект.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
РаботаСФайламиВТомахСлужебный.УдалитьДанныеФайла(ФайлОбъект, ТекстОписания);
Иначе
УдалитьЗаписьИзРегистраДвоичныеДанныеФайлов(ФайлСсылка);
ФайлОбъект.Описание = ТекстОписания + ФайлОбъект.Описание;
ФайлОбъект.Записать();
ФайлОбъект.УстановитьПометкуУдаления(Истина);
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Если Не ПустаяСтрока(ИмяФайлаСПутем) Тогда
// Записать ошибку в журнал регистрации.
ЗаписьЖурналаРегистрации(НСтр("ru = 'Очистка ненужных файлов'", ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка,, ФайлСсылка, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
// Вернем файл на прежнее место в случае ошибки.
ПереместитьФайл(ИмяФайлаСПутемДляУдаления, ИмяФайлаСПутем);
КонецЕсли;
КонецПопытки;
КонецПроцедуры
// Для передачи пути каталога файлов в обработчик ПриОтправкеДанныхФайла.
//
Процедура СохранитьНастройку(КлючОбъекта, КлючНастроек, Настройки)
УстановитьПривилегированныйРежим(Истина);
ХранилищеОбщихНастроек.Сохранить(КлючОбъекта, КлючНастроек, Настройки);
КонецПроцедуры
// Только для внутреннего использования.
//
Процедура ПриОтправкеФайла(ЭлементДанных, ОтправкаЭлемента, Знач СозданиеНачальногоОбраза = Ложь, Получатель = Неопределено)
// Для обменов не РИБ используется алгоритм обычного сеанса обмена, а не создания начального образа,
// т.к. параметра СозданиеНачальногоОбраза равный Истина означает начальную выгрузку данных.
Если СозданиеНачальногоОбраза И Получатель <> Неопределено
И Не ЭтоУзелРаспределеннойИнформационнойБазы(Получатель.Ссылка) Тогда
СозданиеНачальногоОбраза = Ложь;
КонецЕсли;
Если ОтправкаЭлемента = ОтправкаЭлементаДанных.Удалить
ИЛИ ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать Тогда
// Стандартную обработку не переопределяем.
ИначеЕсли ТипЗнч(ЭлементДанных) = Тип("СправочникОбъект.ВерсииФайлов") Тогда
Если СозданиеНачальногоОбраза Тогда
Если ЭлементДанных.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
Если Получатель <> Неопределено
И Получатель.ДополнительныеСвойства.Свойство("РазмещатьФайлыВНачальномОбразе") Тогда
// Помещаем данные файла из тома на диске в служебный реквизит справочника.
РаботаСФайламиВТомахСлужебный.ПоместитьФайлВРеквизитСправочника(ЭлементДанных);
Иначе
// Копируем файл из тома на диске в каталог создания начального образа.
НовыйПутьФайла = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(
Строка(ХранилищеОбщихНастроек.Загрузить("ОбменФайлами", "ВременныйКаталог")),
ЭлементДанных.Ссылка.УникальныйИдентификатор());
РаботаСФайламиВТомахСлужебный.СкопироватьФайл(ЭлементДанных.Ссылка, НовыйПутьФайла);
КонецЕсли;
Иначе
// Если файл хранится в ИБ, то при создании начального образа
// он будет выгружен в составе регистра сведений ХранимыеФайлыВерсий.
КонецЕсли;
Иначе
ОбработатьОтправкуФайлаПоТипуХранения(ЭлементДанных);
КонецЕсли;
ИначеЕсли ТипЗнч(ЭлементДанных) = Тип("РегистрСведенийНаборЗаписей.ДвоичныеДанныеФайлов")
И Не СозданиеНачальногоОбраза Тогда
// Выгрузку регистра выполняем только при создании начального образа.
ОтправкаЭлемента = ОтправкаЭлементаДанных.Игнорировать;
ИначеЕсли НЕ СозданиеНачальногоОбраза
И ЭтоЭлементРаботаСФайлами(ЭлементДанных)
И ТипЗнч(ЭлементДанных) <> Тип("СправочникОбъект.ИдентификаторыОбъектовМетаданных") Тогда
// Справочник ИдентификаторыОбъектовМетаданных может пройти по результатам ЭтоЭлементРаботаСФайлами,
// но не должен обрабатываться здесь.
ОбработатьОтправкуФайлаПоТипуХранения(ЭлементДанных);
КонецЕсли;
КонецПроцедуры
// Только для внутреннего использования.
//
// Параметры:
// Отправитель - ПланОбменаСсылка
//
Процедура ПриПолученииФайла(ЭлементДанных, ПолучениеЭлемента, Отправитель = Неопределено)
ОбработатьПолученныеФайлы = Ложь;
Если ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать Тогда
// Стандартную обработку не переопределяем.
ИначеЕсли ТипЗнч(ЭлементДанных) = Тип("СправочникОбъект.Файлы") Тогда
Если ПолучениеФайлаЗапрещено(ЭлементДанных) Тогда
ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
Возврат;
КонецЕсли;
ОбработатьПолученныеФайлы = Истина;
ИначеЕсли ТипЗнч(ЭлементДанных) = Тип("СправочникОбъект.ВерсииФайлов")
Или (ЭтоЭлементРаботаСФайлами(ЭлементДанных)
И ТипЗнч(ЭлементДанных) <> Тип("СправочникОбъект.ИдентификаторыОбъектовМетаданных")) Тогда
// Справочник ИдентификаторыОбъектовМетаданных может пройти по результатам ЭтоЭлементРаботаСФайлами,
// но не должен обрабатываться здесь.
Если ПолучениеВерсииФайлаЗапрещено(ЭлементДанных) Тогда
ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
Возврат;
КонецЕсли;
ОбработатьПолученныеФайлы = Истина;
КонецЕсли;
Если ОбработатьПолученныеФайлы Тогда
Если Отправитель <> Неопределено
И ПланыОбмена.ИзменениеЗарегистрировано(Отправитель.Ссылка, ЭлементДанных) Тогда
// Коллизия объекта (изменения зарегистрированы и на главном узле и на подчиненном).
ПолучениеЭлемента = ПолучениеЭлементаДанных.Игнорировать;
Возврат;
КонецЕсли;
// Для существующих файлов, размещенных в томах, выполняем их удаление из томов,
// т.к. при получении нового файла он будет заново размещен в томе или информационной базе.
Если Не ЭлементДанных.ЭтоНовый()
И ЭлементДанных.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
СвойстваФайла = РаботаСФайламиВТомахСлужебный.СвойстваФайлаВТоме();
ЗаполнитьЗначенияСвойств(СвойстваФайла, ЭлементДанных);
РаботаСФайламиВТомахСлужебный.УдалитьФайл(
РаботаСФайламиВТомахСлужебный.ПолноеИмяФайлаВТоме(СвойстваФайла));
ЭлементДанных.Том = Справочники.ТомаХраненияФайлов.ПустаяСсылка();
ЭлементДанных.ПутьКФайлу = "";
КонецЕсли;
ДвоичныеДанные = ЭлементДанных.ФайлХранилище.Получить();
Если ТипХраненияФайлов() = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
// По обмену пришел элемент с хранением в базе - но в базе приемнике принято хранить в томах.
// Из служебного реквизита файл размещаем на томе и меняем ТипХраненияФайла на ВТомахНаДиске.
ТипМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(ЭлементДанных));
Если ДвоичныеДанные = Неопределено Тогда
ЭлементДанных.Том = Неопределено;
ЭлементДанных.ПутьКФайлу = Неопределено;
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось добавить файл ""%1"" ни в один из томов, т.к. он отсутствует.
|Возможно, файл удален антивирусной программой.
|Обратитесь к администратору.'"),
ОбщегоНазначенияКлиентСервер.ПолучитьИмяСРасширением(ЭлементДанных.Наименование, ЭлементДанных.Расширение));
ЗаписьЖурналаРегистрации(НСтр("ru = 'Файлы.Добавление файла в том'", ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка, ТипМетаданных, ЭлементДанных.Ссылка, ТекстОшибки);
Иначе
РаботаСФайламиВТомахСлужебный.ДобавитьФайл(ЭлементДанных, ДвоичныеДанные, , Истина);
КонецЕсли;
Иначе
Если ТипЗнч(ДвоичныеДанные) = Тип("ДвоичныеДанные") Тогда
ЭлементДанных.ДополнительныеСвойства.Вставить("ДвоичныеДанныеФайла", ДвоичныеДанные);
КонецЕсли;
ЭлементДанных.ФайлХранилище = Новый ХранилищеЗначения(Неопределено);
ЭлементДанных.Том = Справочники.ТомаХраненияФайлов.ПустаяСсылка();
ЭлементДанных.ПутьКФайлу = "";
ЭлементДанных.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
// Возвращает Истина, если это элемент данных, относящийся к подсистеме РаботаСФайлами.
//
Функция ЭтоЭлементРаботаСФайлами(ЭлементДанных)
ТипЭлементаДанных = ТипЗнч(ЭлементДанных);
Если ТипЭлементаДанных = Тип("УдалениеОбъекта") Тогда
Возврат Ложь;
КонецЕсли;
МетаданныеЭлемента = ЭлементДанных.Метаданные();
Возврат ОбщегоНазначения.ЭтоСправочник(МетаданныеЭлемента)
И (Метаданные.ОпределяемыеТипы.ПрисоединенныйФайлОбъект.Тип.СодержитТип(ТипЭлементаДанных)
ИЛИ (Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип.СодержитТип(ТипЭлементаДанных)));
КонецФункции
// Записывает двоичные данные файла в информационную базу.
//
// Параметры:
// ПрисоединенныйФайл - ОпределяемыйТип.ПрисоединенныйФайл - ссылка на присоединенный файл.
// ДвоичныеДанные - ДвоичныеДанные - которые требуется записать.
//
Процедура ЗаписатьФайлВИнформационнуюБазу(Знач ПрисоединенныйФайл, Знач ДвоичныеДанные) Экспорт
УстановитьОтключениеБезопасногоРежима(Истина);
УстановитьПривилегированныйРежим(Истина);
МенеджерЗаписи = РегистрыСведений.ДвоичныеДанныеФайлов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Файл = ПрисоединенныйФайл;
МенеджерЗаписи.ДвоичныеДанныеФайла = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
МенеджерЗаписи.Записать(Истина);
КонецПроцедуры
// Возвращает новый идентификатор объекта.
// Для получения нового идентификатора выбирает последний идентификатор объекта
// из регистра НаличиеПрисоединенныхФайлов увеличивает его значение
// на одну единицу и возвращает полученный результат.
//
// Возвращаемое значение:
// Строка - строка (10) - новый идентификатор объекта.
//
Функция ПолучитьОчереднойИдентификаторОбъекта() Экспорт
// Вычисление нового идентификатора объекта.
Результат = "0000000000"; // По длине ресурса ИдентификаторОбъекта.
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 1
| НаличиеФайлов.ИдентификаторОбъекта КАК ИдентификаторОбъекта
|ИЗ
| РегистрСведений.НаличиеФайлов КАК НаличиеФайлов
|
|УПОРЯДОЧИТЬ ПО
| ИдентификаторОбъекта УБЫВ";
Запрос = Новый Запрос;
Запрос.Текст = ТекстЗапроса;
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Идентификатор = Выборка.ИдентификаторОбъекта;
Если ПустаяСтрока(Идентификатор) Тогда
Возврат Результат;
КонецЕсли;
// Правила вычисления, как в обычном сложении: при
// заполнении текущего разряда следующий разряд увеличивается
// на единицу, при этом, в текущем разряде значение становится
// равным нулю. Значениями разрядов выступают символы
// [0..9] и [a..z]. Таким образом один разряд может содержать
// 36 значений.
Позиция = 10; // 9- индекс 10-го символа
Пока Позиция > 0 Цикл
Символ = Сред(Идентификатор, Позиция, 1);
Если Символ = "z" Тогда
Идентификатор = Лев(Идентификатор, Позиция-1) + "0" + Прав(Идентификатор, 10 - Позиция);
Позиция = Позиция - 1;
Продолжить;
ИначеЕсли Символ = "9" Тогда
НовыйСимвол = "a";
Иначе
НовыйСимвол = Символ(КодСимвола(Символ)+1);
КонецЕсли;
Идентификатор = Лев(Идентификатор, Позиция-1) + НовыйСимвол + Прав(Идентификатор, 10 - Позиция);
Прервать;
КонецЦикла;
Результат = Идентификатор;
КонецЕсли;
Возврат Результат;
КонецФункции
// См. РаботаСФайламиСлужебныйВМоделиСервиса.ОбновитьСостояниеОчередиИзвлеченияТекста.
Процедура ОбновитьСостояниеОчередиИзвлеченияТекста(ИсточникТекста, СостояниеИзвлеченияТекста) Экспорт
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.РаботаСФайламиВМоделиСервиса")
И ОбщегоНазначения.РазделениеВключено()
И ОбщегоНазначения.ДоступноИспользованиеРазделенныхДанных() Тогда
МодульРаботаСФайламиСлужебныйВМоделиСервиса = ОбщегоНазначения.ОбщийМодуль("РаботаСФайламиСлужебныйВМоделиСервиса");
МодульРаботаСФайламиСлужебныйВМоделиСервиса.ОбновитьСостояниеОчередиИзвлеченияТекста(ИсточникТекста, СостояниеИзвлеченияТекста);
КонецЕсли;
КонецПроцедуры
#Область ДругиеПроцедурыИФункции
// Возвращает имя справочника для указанного владельца или вызывает исключение,
// если их более одного.
//
// Параметры:
// ВладелецФайлов - ЛюбаяСсылка - объект, к которому добавляется файл.
// ИмяСправочника - Строка - если заполнено, то выполняется проверка
// наличия справочника среди справочников владельца для хранения файлов.
// Если не заполнено, возвращает имя основного справочника.
// ЗаголовокОшибки - Строка - заголовок ошибки.
// - Неопределено - не вызывать исключение, а вернуть пустую строку.
// ИмяПараметра - Строка - имя требуемого параметра для определения имени справочника.
// ОкончаниеОшибки - Строка - окончание ошибки (только для случая, когда ИмяПараметра = Неопределено).
//
// Возвращаемое значение:
// Строка - имя справочника
//
Функция ИмяСправочникаХраненияФайлов(ВладелецФайлов, ИмяСправочника = "",
ЗаголовокОшибки = Неопределено, ОкончаниеОшибки = Неопределено) Экспорт
НеВызыватьИсключение = (ЗаголовокОшибки = Неопределено);
ИменаСправочников = ИменаСправочниковХраненияФайлов(ВладелецФайлов, НеВызыватьИсключение);
Если ИменаСправочников.Количество() = 0 Тогда
Если НеВызыватьИсключение Тогда
Возврат "";
КонецЕсли;
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
ЗаголовокОшибки + Символы.ПС
+ НСтр("ru = 'У владельца файлов ""%1"" типа ""%2""
|нет справочников для хранения файлов.'"),
Строка(ВладелецФайлов),
Строка(ТипЗнч(ВладелецФайлов)));
КонецЕсли;
Если ЗначениеЗаполнено(ИмяСправочника) Тогда
Если ИменаСправочников[ИмяСправочника] <> Неопределено Тогда
Возврат ИмяСправочника;
КонецЕсли;
Если НеВызыватьИсключение Тогда
Возврат "";
КонецЕсли;
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
ЗаголовокОшибки + Символы.ПС
+ НСтр("ru = 'У владельца файлов ""%1"" типа ""%2""
|нет справочника ""%3"" для хранения файлов.'"),
Строка(ВладелецФайлов),
Строка(ТипЗнч(ВладелецФайлов)),
Строка(ИмяСправочника));
КонецЕсли;
ОсновнойСправочник = "";
Для каждого КлючИЗначение Из ИменаСправочников Цикл
Если КлючИЗначение.Значение = Истина Тогда
ОсновнойСправочник = КлючИЗначение.Ключ;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЗначениеЗаполнено(ОсновнойСправочник) Тогда
Возврат ОсновнойСправочник;
КонецЕсли;
Если НеВызыватьИсключение Тогда
Возврат "";
КонецЕсли;
ШаблонПричиныОшибки =
НСтр("ru = 'У владельца файлов ""%1"" типа ""%2""
|не указан основной справочник для хранения файлов.'") + Символы.ПС;
ПричинаОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
ШаблонПричиныОшибки, Строка(ВладелецФайлов), Строка(ТипЗнч(ВладелецФайлов)));
ТекстОшибки = ЗаголовокОшибки + Символы.ПС
+ ПричинаОшибки + Символы.ПС
+ ОкончаниеОшибки;
ВызватьИсключение СокрЛП(ТекстОшибки);
КонецФункции
// Возвращает соответствие имен справочников и значения Булево
// для указанного владельца.
//
// Параметры:
// ВладелецФайлов - ЛюбаяСсылка - объект, к которому добавляется файл.
//
// Возвращаемое значение:
// Соответствие из КлючИЗначение:
// * Ключ - Строка
// * Значение - Булево
//
Функция ИменаСправочниковХраненияВерсийФайлов(ВладелецФайлов, НеВызыватьИсключение = Ложь)
Если ТипЗнч(ВладелецФайлов) = Тип("Тип") Тогда
ТипВладельцаФайлов = ВладелецФайлов;
Иначе
ТипВладельцаФайлов = ТипЗнч(ВладелецФайлов);
КонецЕсли;
МетаданныеВладельца = Метаданные.НайтиПоТипу(ТипВладельцаФайлов);
ИменаСправочников = Новый Соответствие;
ИмяСтандартногоОсновногоСправочника = МетаданныеВладельца.Имя + "ВерсииПрисоединенныхФайлов";
Если Метаданные.Справочники.Найти(ИмяСтандартногоОсновногоСправочника) <> Неопределено Тогда
ИменаСправочников.Вставить(ИмяСтандартногоОсновногоСправочника, Истина);
КонецЕсли;
Если Метаданные.ОпределяемыеТипы.ВладелецФайлов.Тип.СодержитТип(ТипВладельцаФайлов) Тогда
ИменаСправочников.Вставить("ВерсииФайлов", Истина);
КонецЕсли;
ОсновнойСправочникУказан = Ложь;
Для каждого КлючИЗначение Из ИменаСправочников Цикл
Если Метаданные.Справочники.Найти(КлючИЗначение.Ключ) = Неопределено Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка при определении имен справочников для хранения версий файлов.
|У владельца файлов типа ""%1""
|указан несуществующий справочник ""%2"".'"),
Строка(ТипВладельцаФайлов),
Строка(КлючИЗначение.Ключ));
ИначеЕсли Не СтрЗаканчиваетсяНа(КлючИЗначение.Ключ, "ВерсииПрисоединенныхФайлов") И Не КлючИЗначение.Ключ ="ВерсииФайлов" Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка при определении имен справочников для хранения версий файлов.
|У владельца файлов типа ""%1""
|указано имя справочника ""%2""
|без окончания ""ВерсииПрисоединенныхФайлов"".'"),
Строка(ТипВладельцаФайлов),
Строка(КлючИЗначение.Ключ));
ИначеЕсли КлючИЗначение.Значение = Неопределено Тогда
ИменаСправочников.Вставить(КлючИЗначение.Ключ, Ложь);
ИначеЕсли КлючИЗначение.Значение = Истина Тогда
Если ОсновнойСправочникУказан Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Ошибка при определении имен справочников для хранения версий файлов.
|У владельца файлов типа ""%1""
|основной справочник версий указан более одного раза.'"),
Строка(ТипВладельцаФайлов),
Строка(КлючИЗначение.Ключ));
КонецЕсли;
ОсновнойСправочникУказан = Истина;
КонецЕсли;
КонецЦикла;
Возврат ИменаСправочников;
КонецФункции
// Возвращает имя справочника для указанного владельца или вызывает исключение,
// если их более одного.
//
// Параметры:
// ВладелецФайлов - ЛюбаяСсылка - объект, к которому добавляется файл.
// ИмяСправочника - Строка - если заполнено, то выполняется проверка
// наличия справочника среди справочников владельца для хранения файлов.
// Если не заполнено, возвращает имя основного справочника.
// ЗаголовокОшибки - Строка - заголовок ошибки.
// - Неопределено - не вызывать исключение, а вернуть пустую строку.
// ИмяПараметра - Строка - имя требуемого параметра для определения имени справочника.
// ОкончаниеОшибки - Строка - окончание ошибки (только для случая, когда ИмяПараметра = Неопределено).
//
// Возвращаемое значение:
// Строка - имя справочника
//
Функция ИмяСправочникаХраненияВерсийФайлов(ВладелецФайлов, ИмяСправочника = "",
ЗаголовокОшибки = Неопределено, ОкончаниеОшибки = Неопределено) Экспорт
НеВызыватьИсключение = (ЗаголовокОшибки = Неопределено);
ИменаСправочников = ИменаСправочниковХраненияВерсийФайлов(ВладелецФайлов, НеВызыватьИсключение);
Если ИменаСправочников.Количество() = 0 Тогда
Возврат "";
КонецЕсли;
ОсновнойСправочник = "";
Для каждого КлючИЗначение Из ИменаСправочников Цикл
Если КлючИЗначение.Значение = Истина Тогда
ОсновнойСправочник = КлючИЗначение.Ключ;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЗначениеЗаполнено(ОсновнойСправочник) Тогда
Возврат ОсновнойСправочник;
КонецЕсли;
Если НеВызыватьИсключение Тогда
Возврат "";
КонецЕсли;
ШаблонПричиныОшибки =
НСтр("ru = 'У владельца версий файлов ""%1""
|не указан основной справочник для хранения версий файлов.'") + Символы.ПС;
ПричинаОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
ШаблонПричиныОшибки, Строка(ВладелецФайлов));
ТекстОшибки = ЗаголовокОшибки + Символы.ПС
+ ПричинаОшибки + Символы.ПС
+ ОкончаниеОшибки;
ВызватьИсключение СокрЛП(ТекстОшибки);
КонецФункции
// Отменяет редактирование файла.
//
// Параметры:
// ПрисоединенныйФайл - ОпределяемыйТип.ПрисоединенныйФайл
// - ОпределяемыйТип.ПрисоединенныйФайлОбъект - ссылка или
// объект присоединенного файла, который требуется освободить.
//
Процедура ОсвободитьФайл(Знач ПрисоединенныйФайл) Экспорт
НачатьТранзакцию();
Попытка
Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(ПрисоединенныйФайл)) Тогда
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ПрисоединенныйФайл)).ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ПрисоединенныйФайл);
БлокировкаДанных.Заблокировать();
ФайлОбъект = ПрисоединенныйФайл.ПолучитьОбъект();
Иначе
ФайлОбъект = ПрисоединенныйФайл;
КонецЕсли;
Если ЗначениеЗаполнено(ФайлОбъект.Редактирует) Тогда
ФайлОбъект.Редактирует = Справочники.Пользователи.ПустаяСсылка();
ФайлОбъект.Записать();
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Функция КоличествоЗанятыхФайлов(Знач ВладелецФайла = Неопределено, Знач Редактирует = Неопределено) Экспорт
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ КОЛИЧЕСТВО(1) КАК Количество
|ИЗ
| РегистрСведений.СведенияОФайлах КАК СведенияОФайлах
|ГДЕ
| СведенияОФайлах.Редактирует <> ЗНАЧЕНИЕ(Справочник.Пользователи.ПустаяСсылка)";
Если Редактирует = Неопределено Тогда
Редактирует = Пользователи.АвторизованныйПользователь();
КонецЕсли;
Запрос.Текст = Запрос.Текст + " И СведенияОФайлах.Редактирует = &Редактирует ";
Запрос.УстановитьПараметр("Редактирует", Редактирует);
Если ВладелецФайла <> Неопределено Тогда
Запрос.Текст = Запрос.Текст + " И СведенияОФайлах.ВладелецФайла = &ВладелецФайла ";
Запрос.УстановитьПараметр("ВладелецФайла", ВладелецФайла);
КонецЕсли;
Выборка = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Количество");
Возврат Выборка[0];
КонецФункции
// Сравнивает 2 элемента отбора компоновки данных.
// Параметры:
// Элемент1 - ЭлементОтбораКомпоновкиДанных
// - ГруппаЭлементовОтбораКомпоновкиДанных - элемент условного оформления списка.
// Элемент2 - ЭлементОтбораКомпоновкиДанных
// - ГруппаЭлементовОтбораКомпоновкиДанных - элемент условного оформления списка.
//
// Возвращаемое значение:
// Булево - результат сравнения.
//
Функция СравнитьЭлементыОтбора(Элемент1, Элемент2)
Если Элемент1.Использование = Элемент2.Использование
И ТипЗнч(Элемент1) = ТипЗнч(Элемент2) Тогда
Если ТипЗнч(Элемент1) = Тип("ЭлементОтбораКомпоновкиДанных") Тогда
Если Элемент1.ВидСравнения <> Элемент2.ВидСравнения
ИЛИ Элемент1.ЛевоеЗначение <> Элемент2.ЛевоеЗначение
ИЛИ Элемент1.ПравоеЗначение <> Элемент2.ПравоеЗначение Тогда
Возврат Ложь;
КонецЕсли;
Иначе
ЧислоЭлементов = Элемент1.Элементы.Количество();
Если Элемент1.ТипГруппы <> Элемент2.ТипГруппы
ИЛИ ЧислоЭлементов <> Элемент2.Элементы.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Для Индекс = 0 По ЧислоЭлементов - 1 Цикл
ПодчиненныйЭлемент1 = Элемент1.Элементы[Индекс];
ПодчиненныйЭлемент2 = Элемент2.Элементы[Индекс];
ЭлементыРавны = СравнитьЭлементыОтбора(ПодчиненныйЭлемент1, ПодчиненныйЭлемент2);
Если Не ЭлементыРавны Тогда
Возврат ЭлементыРавны;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Иначе
Возврат Ложь;
КонецЕсли;
Возврат Истина;
КонецФункции
// Формирует отчет для файлов с ошибками.
//
// Параметры:
// МассивИменФайловСОшибками - Массив из Строка - пути к файлам.
//
// Возвращаемое значение:
// ТабличныйДокумент
//
Функция ИмпортФайловСформироватьОтчет(МассивИменФайловСОшибками) Экспорт
Документ = Новый ТабличныйДокумент;
Макет = Справочники.Файлы.ПолучитьМакет("МакетОтчета");
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьЗаголовок.Параметры.Описание = НСтр("ru = 'Не удалось загрузить следующие файлы:'");
Документ.Вывести(ОбластьЗаголовок);
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого Выборка Из МассивИменФайловСОшибками Цикл
ОбластьСтрока.Параметры.Название = Выборка.ИмяФайла;
ОбластьСтрока.Параметры.Ошибка = Выборка.Ошибка;
Документ.Вывести(ОбластьСтрока);
КонецЦикла;
Отчет = Новый ТабличныйДокумент;
Отчет.Вывести(Документ);
Возврат Отчет;
КонецФункции
// Заполняет условное оформление списка файлов.
//
// Параметры:
// Список - ДинамическийСписок
//
Процедура ЗаполнитьУсловноеОформлениеСпискаФайлов(Список) Экспорт
УсловноеОформлениеКД = Список.КомпоновщикНастроек.Настройки.УсловноеОформление;
УсловноеОформлениеКД.ИдентификаторПользовательскойНастройки = "ОсновноеОформление";
Элемент = УсловноеОформлениеКД.Элементы.Добавить();
Элемент.Использование = Истина;
Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветаСтиля.ТекстЗапрещеннойЯчейкиЦвет);
ГруппаОтбора = Элемент.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
Отбор = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.Использование = Истина;
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Заполнено;
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Редактирует");
Отбор = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.Использование = Истина;
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Служебный");
Отбор.ПравоеЗначение = Ложь;
Если ЕстьДублирующийсяЭлемент(УсловноеОформлениеКД.Элементы, Элемент) Тогда
УсловноеОформлениеКД.Элементы.Удалить(Элемент);
КонецЕсли;
Элемент = УсловноеОформлениеКД.Элементы.Добавить();
Элемент.Использование = Истина;
Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветаСтиля.ФайлЗанятыйТекущимПользователем);
ГруппаОтбора = Элемент.Отбор.Элементы.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
Отбор = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.Использование = Истина;
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Редактирует");
Отбор.ПравоеЗначение = Пользователи.АвторизованныйПользователь();
Отбор = ГруппаОтбора.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.Использование = Истина;
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Служебный");
Отбор.ПравоеЗначение = Ложь;
Если ЕстьДублирующийсяЭлемент(УсловноеОформлениеКД.Элементы, Элемент) Тогда
УсловноеОформлениеКД.Элементы.Удалить(Элемент);
КонецЕсли;
Элемент = УсловноеОформлениеКД.Элементы.Добавить();
Элемент.Использование = Истина;
Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветаСтиля.ТекстЗапрещеннойЯчейкиЦвет);
Отбор = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.Использование = Истина;
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Служебный");
Отбор.ПравоеЗначение = Истина;
Если ЕстьДублирующийсяЭлемент(УсловноеОформлениеКД.Элементы, Элемент) Тогда
УсловноеОформлениеКД.Элементы.Удалить(Элемент);
КонецЕсли;
КонецПроцедуры
// Заполняет условное оформление списка папок.
//
// Параметры:
// Папки - ДинамическийСписок
//
Процедура ЗаполнитьУсловноеОформлениеСпискаПапок(Папки) Экспорт
УсловноеОформлениеКД = Папки.КомпоновщикНастроек.Настройки.УсловноеОформление;
УсловноеОформлениеКД.ИдентификаторПользовательскойНастройки = "ОсновноеОформление";
Элемент = УсловноеОформлениеКД.Элементы.Добавить();
Элемент.Использование = Истина;
Элемент.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветаСтиля.ТекстЗапрещеннойЯчейкиЦвет);
Отбор = Элемент.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.Использование = Истина;
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Заполнено;
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ПапкаСинхронизируется");
Отбор.ПравоеЗначение = Истина;
Если ЕстьДублирующийсяЭлемент(УсловноеОформлениеКД.Элементы, Элемент) Тогда
УсловноеОформлениеКД.Элементы.Удалить(Элемент);
КонецЕсли;
КонецПроцедуры
// Есть ли дублирующийся элемент в условном оформлении списка.
// Параметры:
// Элементы - Массив из ЭлементУсловногоОформления - массив элементов условного оформления списка.
// ЭлементПоиска - ЭлементУсловногоОформления - элемент условного оформления списка.
//
// Возвращаемое значение:
// Булево - есть дублирующийся элемент.
//
Функция ЕстьДублирующийсяЭлемент(Элементы, ЭлементПоиска)
Для Каждого Элемент Из Элементы Цикл
Если Элемент <> ЭлементПоиска Тогда
Если Элемент.Оформление.Элементы.Количество() <> ЭлементПоиска.Оформление.Элементы.Количество() Тогда
Продолжить;
КонецЕсли;
НайденОтличающийсяЭлемент = Ложь;
// Обходим все элементы оформления - если есть хоть один отличающийся - делаем Продолжить;
ЧислоЭлементов = Элемент.Оформление.Элементы.Количество();
Для Индекс = 0 По ЧислоЭлементов - 1 Цикл
Элемент1 = Элемент.Оформление.Элементы[Индекс]; // ЗначениеПараметраНастроекКомпоновкиДанных
Элемент2 = ЭлементПоиска.Оформление.Элементы[Индекс]; // ЗначениеПараметраНастроекКомпоновкиДанных
Если Элемент1.Использование И Элемент2.Использование Тогда
Если Элемент1.Параметр <> Элемент2.Параметр ИЛИ Элемент1.Значение <> Элемент2.Значение Тогда
НайденОтличающийсяЭлемент = Истина;
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если НайденОтличающийсяЭлемент Тогда
Продолжить;
КонецЕсли;
Если Элемент.Отбор.Элементы.Количество() <> ЭлементПоиска.Отбор.Элементы.Количество() Тогда
Продолжить;
КонецЕсли;
// Обходим все элементы отбора - если есть хоть один отличающийся - делаем Продолжить;
ЧислоЭлементов = Элемент.Отбор.Элементы.Количество();
Для Индекс = 0 По ЧислоЭлементов - 1 Цикл
Элемент1 = Элемент.Отбор.Элементы[Индекс];
Элемент2 = ЭлементПоиска.Отбор.Элементы[Индекс];
ЭлементыРавны = СравнитьЭлементыОтбора(Элемент1, Элемент2);
Если Не ЭлементыРавны Тогда
НайденОтличающийсяЭлемент = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если НайденОтличающийсяЭлемент Тогда
Продолжить;
КонецЕсли;
// Обошли все элементы оформления и отбора - они все одинаковы - это дубль.
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
// Делает ПоместитьВоВременноеХранилище (если файл хранится на диске) и возвращает нужную ссылку.
// Параметры:
// ВерсияСсылка - СправочникСсылка.ВерсииФайлов - версия файла.
// ИдентификаторФормы - УникальныйИдентификатор
// - Неопределено - уникальный идентификатор формы.
//
// Возвращаемое значение:
// Строка - навигационная ссылка.
//
Функция ПолучитьНавигационнуюСсылкуВоВременномХранилище(ВерсияСсылка, ИдентификаторФормы = Неопределено) Экспорт
Адрес = "";
ТипХраненияФайла = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ВерсияСсылка, "ТипХраненияФайла");
Если ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
ДвоичныеДанные = РаботаСФайламиВТомахСлужебный.ДанныеФайла(ВерсияСсылка);
Адрес = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ИдентификаторФормы);
Иначе
ХранилищеФайла = РаботаСФайлами.ХранилищеФайлаИзИнформационнойБазы(ВерсияСсылка);
ДвоичныеДанные = ХранилищеФайла.Получить();
Адрес = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ИдентификаторФормы);
КонецЕсли;
Возврат Адрес;
КонецФункции
// Получает значение настройки ПоказыватьКолонкуРазмер.
// Возвращаемое значение:
// Булево - показывать колонку размер.
//
Функция ПолучитьПоказыватьКолонкуРазмер() Экспорт
ПоказыватьКолонкуРазмер = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("НастройкиПрограммы", "ПоказыватьКолонкуРазмер");
Если ПоказыватьКолонкуРазмер = Неопределено Тогда
ПоказыватьКолонкуРазмер = Ложь;
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить("НастройкиПрограммы", "ПоказыватьКолонкуРазмер", ПоказыватьКолонкуРазмер);
КонецЕсли;
Возврат ПоказыватьКолонкуРазмер;
КонецФункции
// Возвращает стандартный текст ошибки.
Функция ОшибкаФайлНеНайденВХранилищеФайлов(ИмяФайла, ПоискВТоме = Истина, ВладелецФайла = "") Экспорт
Если ПоискВТоме Тогда
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось открыть файл:
|%1
|который присоединен к:
|%2
|по причине: двоичные данные файла были удалены. Возможно, файл очищен как ненужный или удален антивирусной программой.
|Обратитесь к администратору.'"),
ИмяФайла,
ВладелецФайла);
Иначе
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось открыть файл:
|%1
|который присоединен к:
|%2
|по причине: двоичные данные файла были удалены. Возможно, файл очищен как ненужный.
|Обратитесь к администратору.'"),
ИмяФайла,
ВладелецФайла);
КонецЕсли;
Возврат ТекстОшибки;
КонецФункции
// Возвращает номер по нарастанию. Предыдущее значение берется из регистра сведений НомераОтсканированныхФайлов.
// Параметры:
// Владелец - ЛюбаяСсылка - владелец файла.
//
// Возвращаемое значение:
// Число - новый номер для сканирования.
//
Функция ПолучитьНовыйНомерДляСканирования(Владелец) Экспорт
// Подготовить структуру отбора по измерениям.
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("Владелец", Владелец);
НачатьТранзакцию();
Попытка
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.НомераОтсканированныхФайлов");
ЭлементБлокировки.УстановитьЗначение("Владелец", Владелец);
Блокировка.Заблокировать();
// Получить структуру с данными ресурсов записи.
СтруктураРесурсов = РегистрыСведений.НомераОтсканированныхФайлов.Получить(СтруктураОтбора);
// Получить максимальный номер из регистра.
Номер = СтруктураРесурсов.Номер;
Номер = Номер + 1; // увеличим на 1
УстановитьОтключениеБезопасногоРежима(Истина);
УстановитьПривилегированныйРежим(Истина);
// Запишем новый номер в регистр.
НаборЗаписей = РегистрыСведений.НомераОтсканированныхФайлов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Владелец.Установить(Владелец);
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Владелец = Владелец;
НоваяЗапись.Номер = Номер;
НаборЗаписей.Записать();
УстановитьПривилегированныйРежим(Ложь);
УстановитьОтключениеБезопасногоРежима(Ложь);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Возврат Номер;
КонецФункции
// Определяет наличие опционального реквизита Служебный в метаданных справочника.
//
// Параметры:
// ИмяСправочника - Строка - имя справочника в метаданных.
//
// Возвращаемое значение:
// Булево - наличие реквизита Служебный.
//
Функция ЕстьРеквизитСлужебный(Знач ИмяСправочника) Экспорт
ОбъектМетаданных = Метаданные.Справочники[ИмяСправочника];
РеквизитСлужебный = ОбъектМетаданных.Реквизиты.Найти("Служебный");
Возврат РеквизитСлужебный <> Неопределено;
КонецФункции
// Добавляет элементы отбора компоновки данных в динамические списки файлов.
//
// Параметры:
// Список - ДинамическийСписок - динамический список, в который будут добавлены отборы.
//
Процедура ДобавитьОтборыВСписокФайлов(Список) Экспорт
ОбщегоНазначенияКлиентСервер.ДобавитьЭлементКомпоновки(Список.Отбор, "Служебный", ВидСравненияКомпоновкиДанных.НеРавно,
Истина, "СкрыватьСлужебные", Истина);
УстановитьОтборПоПометкеУдаления(Список.Отбор);
КонецПроцедуры
// Изменяет видимость элементов формы присоединенного файла для работы внешних пользователей.
// Внешним пользователям доступна только общая информация о файле и его характеристиках.
//
// Параметры:
// Форма - ФормаКлиентскогоПриложения - форма, для которой изменяется видимость элементов.
// ЭтоФормаСписка - Булево - признак того, что процедура вызывается из формы списка.
//
Процедура ИзменитьФормуДляВнешнегоПользователя(Форма, Знач ЭтоФормаСписка = Ложь) Экспорт
Элементы = Форма.Элементы;
Если ЭтоФормаСписка Тогда
Элементы.СписокАвтор.Видимость = Ложь;
Элементы.СписокРедактирует.Видимость = Ложь;
Элементы.СписокНомерКартинкиПодписанЗашифрован.Видимость = Ложь;
Если Элементы.Найти("СписокОтредактировал") <> Неопределено Тогда
Элементы.СписокОтредактировал.Видимость = Ложь;
КонецЕсли;
Иначе
Элементы.ГруппаХарактеристикиФайла.Видимость = Истина;
Элементы.ГруппаДополнительныеДанныеСтраницы.Видимость = Ложь;
Элементы.ФормаГруппаКомандЭлектроннаяПодписьИШифрование.Видимость = Ложь;
КонецЕсли;
КонецПроцедуры
Процедура УстановитьОтборПоПометкеУдаления(Область) Экспорт
ОбщегоНазначенияКлиентСервер.ДобавитьЭлементКомпоновки(Область, "ПометкаУдаления",
ВидСравненияКомпоновкиДанных.Равно, Ложь, "СкрыватьПометкуУдаленияПоУмолчанию", Истина,
РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный);
КонецПроцедуры
#КонецОбласти
#Область ПользовательскиеНастройки
// Считаем ДействиеПоДвойномуЩелчкуМыши - если первый раз - поставим правильное значение.
//
// Возвращаемое значение:
// Строка - действие по двойному щелчку мыши.
//
Функция ДействиеПоДвойномуЩелчкуМыши()
КакОткрывать = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить(
"НастройкиОткрытияФайлов", "ДействиеПоДвойномуЩелчкуМыши");
Если КакОткрывать = Неопределено
ИЛИ КакОткрывать = Перечисления.ДействияСФайламиПоДвойномуЩелчку.ПустаяСсылка() Тогда
КакОткрывать = Перечисления.ДействияСФайламиПоДвойномуЩелчку.ОткрыватьФайл;
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить(
"НастройкиОткрытияФайлов", "ДействиеПоДвойномуЩелчкуМыши", КакОткрывать);
КонецЕсли;
Если КакОткрывать = Перечисления.ДействияСФайламиПоДвойномуЩелчку.ОткрыватьФайл Тогда
Возврат "ОткрыватьФайл";
Иначе
Возврат "ОткрыватьКарточку";
КонецЕсли;
КонецФункции
// Считаем из настроек СпособСравненияВерсийФайлов.
//
// Возвращаемое значение:
// Строка - способ сравнения версий файлов.
//
Функция СпособСравненияВерсийФайлов()
СпособСравнения = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить(
"НастройкиСравненияФайлов", "СпособСравненияВерсийФайлов");
Если СпособСравнения = Перечисления.СпособыСравненияВерсийФайлов.MicrosoftOfficeWord Тогда
Возврат "MicrosoftOfficeWord";
ИначеЕсли СпособСравнения = Перечисления.СпособыСравненияВерсийФайлов.OpenOfficeOrgWriter Тогда
Возврат "OpenOfficeOrgWriter";
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
// Возвращает настройку - Спрашивать режим редактирования при открытии файла.
// Возвращаемое значение:
// Булево - спрашивать режим редактирования при открытии файла.
//
Функция СпрашиватьРежимРедактированияПриОткрытииФайла()
СпрашиватьРежимРедактированияПриОткрытииФайла =
ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("НастройкиОткрытияФайлов", "СпрашиватьРежимРедактированияПриОткрытииФайла");
Если СпрашиватьРежимРедактированияПриОткрытииФайла = Неопределено Тогда
СпрашиватьРежимРедактированияПриОткрытииФайла = Истина;
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить("НастройкиОткрытияФайлов", "СпрашиватьРежимРедактированияПриОткрытииФайла", СпрашиватьРежимРедактированияПриОткрытииФайла);
КонецЕсли;
Возврат СпрашиватьРежимРедактированияПриОткрытииФайла;
КонецФункции
// Возвращает настройку - режим при открытии файла: просмотр или редактирование.
//
// Возвращаемое значение:
// Строка - режим при открытии файла. Варианты: "Просмотр", "Редактирование".
//
Функция ВариантОткрытияФайла()
ВариантОткрытияФайла =
ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить("НастройкиОткрытияФайлов", "ВариантОткрытияФайла");
Если ВариантОткрытияФайла = Неопределено Тогда
ВариантОткрытияФайла = "Открыть";
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить("НастройкиОткрытияФайлов", "ВариантОткрытияФайла", ВариантОткрытияФайла);
КонецЕсли;
Возврат ВариантОткрытияФайла;
КонецФункции
#КонецОбласти
#Область РаботаСКодировками
// Возвращает таблицу имен кодировок.
//
// Возвращаемое значение:
// СписокЗначений:
// * Значение - Строка - например "ibm852".
// * Представление - Строка - например "ibm852 (Центральноевропейская DOS)".
//
Функция Кодировки() Экспорт
СписокКодировок = Новый СписокЗначений;
СписокКодировок.Добавить("ibm852", НСтр("ru = 'IBM852 (Центральноевропейская DOS)'"));
СписокКодировок.Добавить("ibm866", НСтр("ru = 'IBM866 (Кириллица DOS)'"));
СписокКодировок.Добавить("iso-8859-1", НСтр("ru = 'ISO-8859-1 (Западноевропейская ISO)'"));
СписокКодировок.Добавить("iso-8859-2", НСтр("ru = 'ISO-8859-2 (Центральноевропейская ISO)'"));
СписокКодировок.Добавить("iso-8859-3", НСтр("ru = 'ISO-8859-3 (Латиница 3 ISO)'"));
СписокКодировок.Добавить("iso-8859-4", НСтр("ru = 'ISO-8859-4 (Балтийская ISO)'"));
СписокКодировок.Добавить("iso-8859-5", НСтр("ru = 'ISO-8859-5 (Кириллица ISO)'"));
СписокКодировок.Добавить("iso-8859-7", НСтр("ru = 'ISO-8859-7 (Греческая ISO)'"));
СписокКодировок.Добавить("iso-8859-9", НСтр("ru = 'ISO-8859-9 (Турецкая ISO)'"));
СписокКодировок.Добавить("iso-8859-15", НСтр("ru = 'ISO-8859-15 (Латиница 9 ISO)'"));
СписокКодировок.Добавить("koi8-r", НСтр("ru = 'KOI8-R (Кириллица KOI8-R)'"));
СписокКодировок.Добавить("koi8-u", НСтр("ru = 'KOI8-U (Кириллица KOI8-U)'"));
СписокКодировок.Добавить("us-ascii", НСтр("ru = 'US-ASCII (США)'"));
СписокКодировок.Добавить("utf-8", НСтр("ru = 'UTF-8 (Юникод UTF-8)'"));
СписокКодировок.Добавить("utf-8_WithoutBOM", НСтр("ru = 'UTF-8 (Юникод UTF-8 без BOM)'"));
СписокКодировок.Добавить("windows-1250", НСтр("ru = 'Windows-1250 (Центральноевропейская Windows)'"));
СписокКодировок.Добавить("windows-1251", НСтр("ru = 'windows-1251 (Кириллица Windows)'"));
СписокКодировок.Добавить("windows-1252", НСтр("ru = 'Windows-1252 (Западноевропейская Windows)'"));
СписокКодировок.Добавить("windows-1253", НСтр("ru = 'Windows-1253 (Греческая Windows)'"));
СписокКодировок.Добавить("windows-1254", НСтр("ru = 'Windows-1254 (Турецкая Windows)'"));
СписокКодировок.Добавить("windows-1257", НСтр("ru = 'Windows-1257 (Балтийская Windows)'"));
Возврат СписокКодировок;
КонецФункции
#КонецОбласти
#Область ВспомогательныеПроцедурыИФункции
// Отмечает файл, как редактируемый.
//
// Параметры:
// ПрисоединенныйФайл - ссылка или Объект присоединенного файла, который требуется отметить.
//
Процедура ЗанятьФайлДляРедактированияСервер(Знач ПрисоединенныйФайл, Пользователь = Неопределено) Экспорт
НачатьТранзакцию();
Попытка
Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(ПрисоединенныйФайл)) Тогда
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ПрисоединенныйФайл)).ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ПрисоединенныйФайл);
БлокировкаДанных.Заблокировать();
ФайлОбъект = ПрисоединенныйФайл.ПолучитьОбъект();
ФайлОбъект.Заблокировать();
Иначе
ФайлОбъект = ПрисоединенныйФайл;
КонецЕсли;
Если Пользователь = Неопределено Тогда
ФайлОбъект.Редактирует = Пользователи.АвторизованныйПользователь();
Иначе
ФайлОбъект.Редактирует = Пользователь;
КонецЕсли;
ФайлОбъект.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Процедура ЗаписатьДанныеФайлаВРегистрПриОбмене(Источник)
Перем ДвоичныеДанныеФайла;
Если Источник.ДополнительныеСвойства.Свойство("ДвоичныеДанныеФайла", ДвоичныеДанныеФайла) Тогда
НаборЗаписей = РегистрыСведений.ДвоичныеДанныеФайлов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Файл.Установить(Источник.Ссылка);
Запись = НаборЗаписей.Добавить();
Запись.Файл = Источник.Ссылка;
Запись.ДвоичныеДанныеФайла = Новый ХранилищеЗначения(ДвоичныеДанныеФайла);
НаборЗаписей.ОбменДанными.Загрузка = Истина;
НаборЗаписей.Записать();
Источник.ДополнительныеСвойства.Удалить("ДвоичныеДанныеФайла");
КонецЕсли;
КонецПроцедуры
Функция ПолучениеФайлаЗапрещено(ЭлементДанных)
Возврат ЭлементДанных.ЭтоНовый()
И Не ПроверитьРасширениеФайлаДляЗагрузки(ЭлементДанных.Расширение, Ложь);
КонецФункции
Функция ПолучениеВерсииФайлаЗапрещено(ЭлементДанных)
Возврат ЭлементДанных.ЭтоНовый()
И Не ПроверитьРасширениеФайлаДляЗагрузки(ЭлементДанных.Расширение, Ложь);
КонецФункции
Процедура ОбработатьОтправкуФайлаПоТипуХранения(ЭлементДанных)
Если ЭлементДанных.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
// Помещаем данные файла из тома на диске в служебный реквизит справочника.
РаботаСФайламиВТомахСлужебный.ПоместитьФайлВРеквизитСправочника(ЭлементДанных);
Иначе
// Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе
// Если есть возможность хранения версий файлов - двоичные данные берутся из текущей версии.
Если ЭлементДанных.Метаданные().Реквизиты.Найти("ТекущаяВерсия") <> Неопределено
И ЗначениеЗаполнено(ЭлементДанных.ТекущаяВерсия) Тогда
ИсточникДвоичныхДанных = ЭлементДанных.ТекущаяВерсия;
Иначе
ИсточникДвоичныхДанных = ЭлементДанных.Ссылка;
КонецЕсли;
Попытка
// Помещаем данные файла из информационной базы в служебный реквизит справочника.
АдресВоВременномХранилище = ПолучитьНавигационнуюСсылкуВоВременномХранилище(ИсточникДвоичныхДанных);
ЭлементДанных.ФайлХранилище = Новый ХранилищеЗначения(ПолучитьИзВременногоХранилища(АдресВоВременномХранилище), Новый СжатиеДанных(9));
Исключение
// Возможно, файл не был найден. Отправку данных не прерываем.
ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииДляОбмена(), УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ЭлементДанных.ФайлХранилище = Новый ХранилищеЗначения(Неопределено);
КонецПопытки;
ЭлементДанных.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе;
ЭлементДанных.ПутьКФайлу = "";
ЭлементДанных.Том = Справочники.ТомаХраненияФайлов.ПустаяСсылка();
КонецЕсли;
КонецПроцедуры
// Возвращает массив присоединенных файлов для указанного владельца.
// ссылок на присоединенные файлы.
//
// Параметры:
// ВладелецФайлов - ОпределяемыйТип.ПрисоединенныйФайл
//
// Возвращаемое значение:
// Массив из ОпределяемыйТип.ПрисоединенныйФайл
//
Функция ВсеПодчиненныеФайлы(Знач ВладелецФайлов) Экспорт
УстановитьПривилегированныйРежим(Истина);
ИменаСправочников = ИменаСправочниковХраненияФайлов(ВладелецФайлов);
ТекстЗапросов = "";
Для каждого КлючИЗначение Из ИменаСправочников Цикл
Если ЗначениеЗаполнено(ТекстЗапросов) Тогда
ТекстЗапросов = ТекстЗапросов + "
|ОБЪЕДИНИТЬ ВСЕ
|
|";
КонецЕсли;
ТекстЗапроса =
"ВЫБРАТЬ
| ПрисоединенныеФайлы.Ссылка
|ИЗ
| &ИмяСправочника КАК ПрисоединенныеФайлы
|ГДЕ
| ПрисоединенныеФайлы.ВладелецФайла = &ВладелецФайлов";
Если Метаданные.Справочники[КлючИЗначение.Ключ].Иерархический = Истина Тогда
ТекстЗапроса = ТекстЗапроса + "
| И Не ПрисоединенныеФайлы.ЭтоГруппа";
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяСправочника", "Справочник." + КлючИЗначение.Ключ);
ТекстЗапросов = ТекстЗапросов + ТекстЗапроса;
КонецЦикла;
Запрос = Новый Запрос(ТекстЗапросов);
Запрос.УстановитьПараметр("ВладелецФайлов", ВладелецФайлов);
Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
КонецФункции
// Возвращает строковую константу для формирования сообщений журнала регистрации.
//
// Возвращаемое значение:
// Строка
//
Функция СобытиеЖурналаРегистрацииДляОбмена()
Возврат НСтр("ru = 'Файлы.Не удалось отправить файл при обмене данными'", ОбщегоНазначения.КодОсновногоЯзыка());
КонецФункции
// Заменяет двоичные данные файла в ИБ на данные во временном хранилище.
Процедура ОбновитьДвоичныеДанныеФайлаНаСервере(Знач ПрисоединенныйФайл,
Знач АдресФайлаВоВременномХранилищеДвоичныеДанные,
Знач РеквизитыЗначения = Неопределено)
УстановитьПривилегированныйРежим(Истина);
ЭтоСсылка = Справочники.ТипВсеСсылки().СодержитТип(ТипЗнч(ПрисоединенныйФайл));
НачатьТранзакцию();
Попытка
Если ЭтоСсылка Тогда
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ПрисоединенныйФайл)).ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ПрисоединенныйФайл);
БлокировкаДанных.Заблокировать();
ЗаблокироватьДанныеДляРедактирования(ПрисоединенныйФайл);
ФайлОбъект = ПрисоединенныйФайл.ПолучитьОбъект();
ФайлСсылка = ПрисоединенныйФайл;
Иначе
ФайлОбъект = ПрисоединенныйФайл;
ФайлСсылка = ФайлОбъект.Ссылка;
КонецЕсли;
Если ТипЗнч(АдресФайлаВоВременномХранилищеДвоичныеДанные) = Тип("ДвоичныеДанные") Тогда
ДвоичныеДанные = АдресФайлаВоВременномХранилищеДвоичныеДанные;
Иначе
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресФайлаВоВременномХранилищеДвоичныеДанные);
КонецЕсли;
ФайлОбъект.Изменил = Пользователи.АвторизованныйПользователь();
Если ТипЗнч(РеквизитыЗначения) = Тип("Структура") Тогда
ЗаполнитьЗначенияСвойств(ФайлОбъект, РеквизитыЗначения);
КонецЕсли;
ЭтоФайлВБазе = (ФайлОбъект.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе);
Если ЭтоФайлВБазе Тогда
ОбновитьДвоичныеДанныеФайлаВИнформационнойБазе(ФайлОбъект, ФайлСсылка, ДвоичныеДанные);
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Если Не ЭтоФайлВБазе Тогда
РаботаСФайламиВТомахСлужебный.ОбновитьФайл(ФайлОбъект, ДвоичныеДанные);
КонецЕсли;
КонецПроцедуры
Процедура ОбновитьДвоичныеДанныеФайлаВИнформационнойБазе(ФайлОбъект, ФайлСсылка, ДвоичныеДанные)
Попытка
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.РегистрыСведений.ДвоичныеДанныеФайлов.ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Файл", ФайлСсылка);
БлокировкаДанных.Заблокировать();
МенеджерЗаписи = РегистрыСведений.ДвоичныеДанныеФайлов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Файл = ФайлСсылка;
МенеджерЗаписи.Прочитать();
МенеджерЗаписи.Файл = ФайлСсылка;
МенеджерЗаписи.ДвоичныеДанныеФайла = Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
МенеджерЗаписи.Записать();
ФайлОбъект.Размер = ДвоичныеДанные.Размер();
ФайлОбъект.Записать();
Исключение
ЗаписьЖурналаРегистрации(
НСтр("ru = 'Файлы.Обновление данных присоединенного файла в хранилище файлов'",
ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка,
,
,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
// Создает версию сохраняемого файла для сохранения в ИБ.
//
// Параметры:
// ФайлСсылка - СправочникСсылка.Файлы - файл, для которого создается новая версия.
// СведенияОФайле - см. РаботаСФайламиКлиентСервер.СведенияОФайле
//
// Возвращаемое значение:
// СправочникСсылка.ВерсииФайлов - созданная версия.
//
Функция СоздатьВерсию(ФайлСсылка, СведенияОФайле) Экспорт
ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлСсылка, "Ссылка", Истина);
Если ЕстьПраваНаОбъект = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
Если Не ЗначениеЗаполнено(СведенияОФайле.ВремяИзмененияУниверсальное)
Или СведенияОФайле.ВремяИзмененияУниверсальное > ТекущаяУниверсальнаяДата() Тогда
СведенияОФайле.ВремяИзмененияУниверсальное = ТекущаяУниверсальнаяДата();
КонецЕсли;
Если Не ЗначениеЗаполнено(СведенияОФайле.ВремяИзменения)
Или УниверсальноеВремя(СведенияОФайле.ВремяИзменения) > СведенияОФайле.ВремяИзмененияУниверсальное Тогда
СведенияОФайле.ВремяИзменения = ТекущаяДатаСеанса();
КонецЕсли;
ПроверитьРасширениеФайлаДляЗагрузки(СведенияОФайле.РасширениеБезТочки);
Версия = Справочники.ВерсииФайлов.СоздатьЭлемент();
Если СведенияОФайле.НоваяВерсияНомерВерсии = Неопределено Тогда
Версия.НомерВерсии = НайтиМаксимальныйНомерВерсии(ФайлСсылка) + 1;
Иначе
Версия.НомерВерсии = СведенияОФайле.НоваяВерсияНомерВерсии;
КонецЕсли;
Версия.Владелец = ФайлСсылка;
Версия.ДатаМодификацииУниверсальная = СведенияОФайле.ВремяИзмененияУниверсальное;
Версия.ДатаМодификацииФайла = СведенияОФайле.ВремяИзменения;
Версия.Комментарий = СведенияОФайле.НоваяВерсияКомментарий;
Версия.ИндексКартинки = РаботаСФайламиСлужебныйКлиентСервер.ПолучитьИндексПиктограммыФайла(СведенияОФайле.РасширениеБезТочки);
Если СведенияОФайле.НоваяВерсияАвтор = Неопределено Тогда
Версия.Автор = Пользователи.АвторизованныйПользователь();
Иначе
Версия.Автор = СведенияОФайле.НоваяВерсияАвтор;
КонецЕсли;
Если СведенияОФайле.НоваяВерсияДатаСоздания = Неопределено Тогда
Версия.ДатаСоздания = ТекущаяДатаСеанса();
Иначе
Версия.ДатаСоздания = СведенияОФайле.НоваяВерсияДатаСоздания;
КонецЕсли;
Версия.Размер = СведенияОФайле.Размер;
Версия.Расширение = ОбщегоНазначенияКлиентСервер.РасширениеБезТочки(СведенияОФайле.РасширениеБезТочки);
Версия.Наименование = СведенияОФайле.ИмяБезРасширения;
Версия.ПолноеНаименование = Версия.Наименование;
ТипХраненияФайлов = ТипХраненияФайлов();
Версия.ТипХраненияФайла = ТипХраненияФайлов;
Если СведенияОФайле.СсылкаНаВерсиюИсточник <> Неопределено Тогда // создание Файла из шаблона
ТипХраненияФайловШаблона = СведенияОФайле.СсылкаНаВерсиюИсточник.ТипХраненияФайла;
Если ТипХраненияФайловШаблона = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе
И ТипХраненияФайлов = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
// И шаблон, и новый Файл - в базе.
// При создании Файла из шаблона хранилище значения копируется напрямую.
ДвоичныеДанныеИлиПуть = СведенияОФайле.АдресВременногоХранилищаФайла.Получить();
ИначеЕсли ТипХраненияФайловШаблона = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске
И ТипХраненияФайлов = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
// И шаблон, и новый Файл - на диске - просто копируем файл.
Если Не СведенияОФайле.СсылкаНаВерсиюИсточник.Том.Пустая() Тогда
ПолныйПутьФайлаШаблона = РаботаСФайламиВТомахСлужебный.ПолноеИмяФайлаВТоме(
РаботаСФайламиВТомахСлужебный.СвойстваФайлаВТоме(СведенияОФайле.СсылкаНаВерсиюИсточник));
РаботаСФайламиВТомахСлужебный.ДобавитьФайл(Версия, ПолныйПутьФайлаШаблона);
КонецЕсли;
ИначеЕсли ТипХраненияФайловШаблона = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе
И ТипХраненияФайлов = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
// Шаблон в базе, новый Файл - на диске.
// В этом случае в АдресВременногоХранилищаФайла находится ХранилищеЗначения с файлом.
РаботаСФайламиВТомахСлужебный.ДобавитьФайл(Версия, СведенияОФайле.АдресВременногоХранилищаФайла.Получить());
ИначеЕсли ТипХраненияФайловШаблона = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске
И ТипХраненияФайлов = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
// Шаблон на диске, новый Файл - в базе.
Если Не СведенияОФайле.СсылкаНаВерсиюИсточник.Том.Пустая() Тогда
ДвоичныеДанныеИлиПуть = РаботаСФайламиВТомахСлужебный.ДанныеФайла(СведенияОФайле.СсылкаНаВерсиюИсточник);
КонецЕсли;
КонецЕсли;
Иначе // Создание объекта Файл на основе выбранного файла с диска.
Если ЭтоАдресВременногоХранилища(СведенияОФайле.АдресВременногоХранилищаФайла) Тогда
ДвоичныеДанныеИлиПуть = ПолучитьИзВременногоХранилища(СведенияОФайле.АдресВременногоХранилищаФайла); // ДвоичныеДанные
Если Версия.Размер = 0 Тогда
Версия.Размер = ДвоичныеДанныеИлиПуть.Размер();
ПроверитьРазмерФайлаДляЗагрузки(Версия);
КонецЕсли;
Если ТипХраненияФайлов = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
РаботаСФайламиВТомахСлужебный.ДобавитьФайл(Версия, ДвоичныеДанныеИлиПуть);
КонецЕсли;
Иначе
ДвоичныеДанныеИлиПуть = СведенияОФайле.АдресВременногоХранилищаФайла;
ЗаполнитьЗначенияСвойств(Версия, ФайлСсылка, "Том, ПутьКФайлу");
КонецЕсли;
КонецЕсли;
Версия.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
ИспользованиеПолнотекстовогоПоиска = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.Использовать;
Если Метаданные.Справочники.ВерсииФайлов.ПолнотекстовыйПоиск = ИспользованиеПолнотекстовогоПоиска Тогда
Если ТипЗнч(СведенияОФайле.АдресВременногоХранилищаТекста) = Тип("ХранилищеЗначения") Тогда
// При создании Файла из шаблона хранилище значения копируется напрямую.
Версия.ТекстХранилище = СведенияОФайле.АдресВременногоХранилищаТекста;
Версия.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.Извлечен;
ИначеЕсли Не ПустаяСтрока(СведенияОФайле.АдресВременногоХранилищаТекста) Тогда
РезультатИзвлеченияТекста = ИзвлечьТекст(СведенияОФайле.АдресВременногоХранилищаТекста);
Версия.ТекстХранилище = РезультатИзвлеченияТекста.ТекстХранилище;
Версия.СтатусИзвлеченияТекста = РезультатИзвлеченияТекста.СтатусИзвлеченияТекста;
КонецЕсли;
КонецЕсли;
Версия.Заполнить(Неопределено);
Версия.Записать();
Если ТипХраненияФайлов = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
ЗаписатьФайлВИнформационнуюБазу(Версия.Ссылка, ДвоичныеДанныеИлиПуть);
КонецЕсли;
Возврат Версия.Ссылка;
КонецФункции
// Обновляет свойства файла БЕЗ учета версий - двоичные данные, текст, дату изменения,
// а также другие необязательные свойства.
//
Процедура ОбновитьФайл(ИнформацияОФайле, ПрисоединенныйФайл) Экспорт
ОбщегоНазначенияКлиентСервер.ПроверитьПараметр("РаботаСФайлами.ДвоичныеДанныеФайла", "ПрисоединенныйФайл",
ПрисоединенныйФайл, Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип);
РеквизитыЗначения = Новый Структура;
Если ИнформацияОФайле.Свойство("ИмяБезРасширения") И ЗначениеЗаполнено(ИнформацияОФайле.ИмяБезРасширения) Тогда
РеквизитыЗначения.Вставить("Наименование", ИнформацияОФайле.ИмяБезРасширения);
КонецЕсли;
Если НЕ ИнформацияОФайле.Свойство("ДатаМодификацииУниверсальная")
ИЛИ НЕ ЗначениеЗаполнено(ИнформацияОФайле.ДатаМодификацииУниверсальная)
ИЛИ ИнформацияОФайле.ДатаМодификацииУниверсальная > ТекущаяУниверсальнаяДата() Тогда
// Заполнение текущей даты в формате универсального времени.
РеквизитыЗначения.Вставить("ДатаМодификацииУниверсальная", ТекущаяУниверсальнаяДата());
Иначе
РеквизитыЗначения.Вставить("ДатаМодификацииУниверсальная", ИнформацияОФайле.ДатаМодификацииУниверсальная);
КонецЕсли;
Если ИнформацияОФайле.Свойство("Редактирует") Тогда
РеквизитыЗначения.Вставить("Редактирует", ИнформацияОФайле.Редактирует);
КонецЕсли;
Если ИнформацияОФайле.Свойство("Расширение") Тогда
РеквизитыЗначения.Вставить("Расширение", ИнформацияОФайле.Расширение);
КонецЕсли;
Если ИнформацияОФайле.Свойство("Кодировка") И Не ПустаяСтрока(ИнформацияОФайле.Кодировка) Тогда
РегистрыСведений.КодировкиФайлов.ЗаписатьКодировкуВерсииФайла(ПрисоединенныйФайл, ИнформацияОФайле.Кодировка);
КонецЕсли;
ДвоичныеДанные = ПолучитьИзВременногоХранилища(ИнформацияОФайле.АдресФайлаВоВременномХранилище);
МетаданныеФайла = Метаданные.НайтиПоТипу(ТипЗнч(ПрисоединенныйФайл));
ИспользованиеПолнотекстовогоПоиска = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.Использовать;
Если МетаданныеФайла.ПолнотекстовыйПоиск = ИспользованиеПолнотекстовогоПоиска Тогда
РезультатИзвлеченияТекста = ИзвлечьТекст(ИнформацияОФайле.АдресВременногоХранилищаТекста, ДвоичныеДанные,
ПрисоединенныйФайл.Расширение);
РеквизитыЗначения.Вставить("СтатусИзвлеченияТекста", РезультатИзвлеченияТекста.СтатусИзвлеченияТекста);
РеквизитыЗначения.Вставить("ТекстХранилище", РезультатИзвлеченияТекста.ТекстХранилище);
Иначе
РеквизитыЗначения.Вставить("СтатусИзвлеченияТекста", Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен);
РеквизитыЗначения.Вставить("ТекстХранилище", Новый ХранилищеЗначения(""));
КонецЕсли;
ОбновитьДвоичныеДанныеФайлаНаСервере(ПрисоединенныйФайл, ДвоичныеДанные, РеквизитыЗначения);
КонецПроцедуры
// Обновляет или создает версию Файла и возвращает ссылку на обновленную версию (или Ложь, если файл бинарно не
// изменен).
//
// Параметры:
// ФайлСсылка - СправочникСсылка.Файлы - файл, для которого создается новая версия.
// СведенияОФайле - см. РаботаСФайламиКлиентСервер.СведенияОФайле
// ВерсияСсылка - СправочникСсылка.ВерсииФайлов - версия файла, которую надо обновить.
// УникальныйИдентификаторФормы - УникальныйИдентификатор - уникальный идентификатор формы,
// в контексте которой выполняется операция.
//
// Возвращаемое значение:
// СправочникСсылка.ВерсииФайлов - созданная или измененная версия; Неопределено, если файл бинарно не был изменен.
//
Функция ОбновитьВерсиюФайла(ФайлСсылка,
СведенияОФайле,
ВерсияСсылка = Неопределено,
УникальныйИдентификаторФормы = Неопределено,
Пользователь = Неопределено) Экспорт
ЕстьПравоСохранения = ПравоДоступа("СохранениеДанныхПользователя", Метаданные);
ЕстьПраваНаОбъект = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлСсылка, "Ссылка", Истина);
Если ЕстьПраваНаОбъект = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
ВремяИзмененияУниверсальное = СведенияОФайле.ВремяИзмененияУниверсальное;
Если НЕ ЗначениеЗаполнено(ВремяИзмененияУниверсальное)
ИЛИ ВремяИзмененияУниверсальное > ТекущаяУниверсальнаяДата() Тогда
ВремяИзмененияУниверсальное = ТекущаяУниверсальнаяДата();
КонецЕсли;
ВремяИзменения = СведенияОФайле.ВремяИзменения;
Если НЕ ЗначениеЗаполнено(ВремяИзменения)
ИЛИ УниверсальноеВремя(ВремяИзменения) > ВремяИзмененияУниверсальное Тогда
ВремяИзменения = ТекущаяДатаСеанса();
КонецЕсли;
ПроверитьРасширениеФайлаДляЗагрузки(СведенияОФайле.РасширениеБезТочки);
ДвоичныеДанные = Неопределено;
МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка));
ВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", МетаданныеОбъекта);
ИспользованиеПолнотекстовогоПоиска = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.Использовать;
ВерсияСсылкаДляСравненияРазмера = ВерсияСсылка;
Если ВерсияСсылка <> Неопределено Тогда
ВерсияСсылкаДляСравненияРазмера = ВерсияСсылка;
ИначеЕсли ВозможностьХранитьВерсии И ЗначениеЗаполнено(ФайлСсылка.ТекущаяВерсия)Тогда
ВерсияСсылкаДляСравненияРазмера = ФайлСсылка.ТекущаяВерсия;
Иначе
ВерсияСсылкаДляСравненияРазмера = ФайлСсылка;
КонецЕсли;
КодировкаПредВерсии = РегистрыСведений.КодировкиФайлов.КодировкаВерсииФайла(ВерсияСсылкаДляСравненияРазмера);
СтруктураРеквизитов = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ВерсияСсылкаДляСравненияРазмера,
"Размер, ТипХраненияФайла, Том, ПутьКФайлу");
ХранилищеФайла = Неопределено;
Если СведенияОФайле.Размер = СтруктураРеквизитов.Размер Тогда
Если СтруктураРеквизитов.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
ДвоичныеДанныеПредыдущейВерсии = РаботаСФайламиВТомахСлужебный.ДанныеФайла(ВерсияСсылкаДляСравненияРазмера);
Иначе
ХранилищеФайла = РаботаСФайлами.ХранилищеФайлаИзИнформационнойБазы(ВерсияСсылкаДляСравненияРазмера);
ДвоичныеДанныеПредыдущейВерсии = ХранилищеФайла.Получить();
КонецЕсли;
ДвоичныеДанные = ПолучитьИзВременногоХранилища(СведенияОФайле.АдресВременногоХранилищаФайла);
Если ДвоичныеДанныеПредыдущейВерсии = ДвоичныеДанные Тогда
Возврат Неопределено; // Файл бинарно не изменен - вернем Ложь.
КонецЕсли;
КонецЕсли;
ВерсияЗаблокирована = Ложь;
Версия = Неопределено;
НачатьТранзакцию();
Попытка
Если СведенияОФайле.ХранитьВерсии Тогда
ЗаголовокОшибки = НСтр("ru = 'Ошибка при записи новой версии присоединенных файлов.'");
ОкончаниеОшибки = НСтр("ru = 'В этом случае запись версии файла невозможна.'");
ИмяСправочникаХранилищаВерсийФайлов = ИмяСправочникаХраненияВерсийФайлов(
ТипЗнч(ФайлСсылка.ВладелецФайла), "", ЗаголовокОшибки, ОкончаниеОшибки);
Версия = Справочники[ИмяСправочникаХранилищаВерсийФайлов].СоздатьЭлемент();
Версия.РодительскаяВерсия = ФайлСсылка.ТекущаяВерсия;
Версия.НомерВерсии = НайтиМаксимальныйНомерВерсии(ФайлСсылка) + 1;
Иначе
СсылкаНаВерсию = ?(ВерсияСсылка = Неопределено, ФайлСсылка.ТекущаяВерсия, ВерсияСсылка);
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить(СсылкаНаВерсию.Метаданные().ПолноеИмя());
ЭлементБлокировки.УстановитьЗначение("Ссылка", СсылкаНаВерсию);
Блокировка.Заблокировать();
Версия = СсылкаНаВерсию.ПолучитьОбъект();
ЗаблокироватьДанныеДляРедактирования(Версия.Ссылка, , УникальныйИдентификаторФормы);
ВерсияЗаблокирована = Истина;
// Удалим файл с диска - мы заместим его новым.
Если Версия.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
СвойстваВерсии = РаботаСФайламиВТомахСлужебный.СвойстваФайлаВТоме();
ЗаполнитьЗначенияСвойств(СвойстваВерсии, Версия);
РаботаСФайламиВТомахСлужебный.УдалитьФайл(РаботаСФайламиВТомахСлужебный.ПолноеИмяФайлаВТоме(СвойстваВерсии));
КонецЕсли;
КонецЕсли;
Версия.Владелец = ФайлСсылка;
Если Пользователь = Неопределено Тогда
Версия.Автор = Пользователи.АвторизованныйПользователь();
Иначе
Версия.Автор = Пользователь;
КонецЕсли;
Версия.ДатаМодификацииУниверсальная = ВремяИзмененияУниверсальное;
Версия.ДатаМодификацииФайла = ВремяИзменения;
Версия.ДатаСоздания = ТекущаяДатаСеанса();
Версия.Размер = СведенияОФайле.Размер;
Версия.ПолноеНаименование = СведенияОФайле.ИмяБезРасширения;
Версия.Наименование = СведенияОФайле.ИмяБезРасширения;
Версия.Комментарий = СведенияОФайле.Комментарий;
Версия.Расширение = ОбщегоНазначенияКлиентСервер.РасширениеБезТочки(СведенияОФайле.РасширениеБезТочки);
ТипХраненияФайлов = ТипХраненияФайлов();
Версия.ТипХраненияФайла = ТипХраненияФайлов;
Если ДвоичныеДанные = Неопределено Тогда
ДвоичныеДанные = ПолучитьИзВременногоХранилища(СведенияОФайле.АдресВременногоХранилищаФайла); // ДвоичныеДанные
КонецЕсли;
Если Версия.Размер = 0 Тогда
Версия.Размер = ДвоичныеДанные.Размер();
ПроверитьРазмерФайлаДляЗагрузки(Версия);
КонецЕсли;
Если ТипХраненияФайлов = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
Версия.ПутьКФайлу = "";
Версия.Том = Справочники.ТомаХраненияФайлов.ПустаяСсылка();
Иначе
РаботаСФайламиВТомахСлужебный.ДобавитьФайл(Версия, ДвоичныеДанные);
КонецЕсли;
Если МетаданныеОбъекта.ПолнотекстовыйПоиск = ИспользованиеПолнотекстовогоПоиска Тогда
РезультатИзвлеченияТекста = ИзвлечьТекст(СведенияОФайле.АдресВременногоХранилищаТекста);
Версия.ТекстХранилище = РезультатИзвлеченияТекста.ТекстХранилище;
Версия.СтатусИзвлеченияТекста = РезультатИзвлеченияТекста.СтатусИзвлеченияТекста;
Если СведенияОФайле.НовыйСтатусИзвлеченияТекста <> Неопределено Тогда
Версия.СтатусИзвлеченияТекста = СведенияОФайле.НовыйСтатусИзвлеченияТекста;
КонецЕсли;
Иначе
Версия.ТекстХранилище = Новый ХранилищеЗначения("");
Версия.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
КонецЕсли;
Версия.Заполнить(Неопределено);
Версия.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Если ТипХраненияФайлов = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
ЗаписатьФайлВИнформационнуюБазу(Версия.Ссылка, ДвоичныеДанные);
КонецЕсли;
Если ВерсияЗаблокирована Тогда
РазблокироватьДанныеДляРедактирования(Версия.Ссылка, УникальныйИдентификаторФормы);
КонецЕсли;
РегистрыСведений.КодировкиФайлов.ЗаписатьКодировкуВерсииФайла(Версия.Ссылка, КодировкаПредВерсии);
Если ЕстьПравоСохранения Тогда
НавигационнаяСсылкаФайла = ПолучитьНавигационнуюСсылку(ФайлСсылка);
ИсторияРаботыПользователя.Добавить(НавигационнаяСсылкаФайла);
КонецЕсли;
Возврат Версия.Ссылка;
КонецФункции
// Подставляет ссылку на версию в карточку Файла.
//
// Параметры:
// ФайлСсылка - СправочникСсылка.Файлы - файл, в котором создается версия.
// Версия - СправочникСсылка.ВерсииФайлов - версия файла.
// АдресВременногоХранилищаТекста - Строка - содержит адрес во временном хранилище, где находятся двоичные данные с
// файлом текста или ХранилищеЗначения - непосредственно содержит двоичные
// данные с файлом текста.
// УникальныйИдентификатор - УникальныйИдентификатор - уникальный идентификатор формы.
//
Процедура ОбновитьВерсиюВФайле(ФайлСсылка,
Версия,
Знач АдресВременногоХранилищаТекста,
УникальныйИдентификатор = Неопределено) Экспорт
ИспользованиеПолнотекстовогоПоиска = Метаданные.СвойстваОбъектов.ИспользованиеПолнотекстовогоПоиска.Использовать;
НачатьТранзакцию();
Попытка
МетаданныеСправочника = Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка));
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(МетаданныеСправочника.ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлСсылка);
БлокировкаДанных.Заблокировать();
ЗаблокироватьДанныеДляРедактирования(ФайлСсылка, , УникальныйИдентификатор);
ФайлОбъект = ФайлСсылка.ПолучитьОбъект();
ХранениеВерсии = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Версия, "ТипХраненияФайла, Том, ПутьКФайлу");
ФайлОбъект.ТекущаяВерсия = Версия;
Если АдресВременногоХранилищаТекста <> Неопределено
И МетаданныеСправочника.ПолнотекстовыйПоиск = ИспользованиеПолнотекстовогоПоиска Тогда
Если ТипЗнч(АдресВременногоХранилищаТекста) = Тип("ХранилищеЗначения") Тогда
// При создании Файла из шаблона хранилище значения копируется напрямую.
ФайлОбъект.ТекстХранилище = АдресВременногоХранилищаТекста;
Иначе
РезультатИзвлеченияТекста = ИзвлечьТекст(АдресВременногоХранилищаТекста);
ФайлОбъект.ТекстХранилище = РезультатИзвлеченияТекста.ТекстХранилище;
ФайлОбъект.СтатусИзвлеченияТекста = РезультатИзвлеченияТекста.СтатусИзвлеченияТекста;
КонецЕсли;
Иначе
ФайлОбъект.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
ФайлОбъект.ТекстХранилище = Новый ХранилищеЗначения("");
КонецЕсли;
ЗаполнитьЗначенияСвойств(ФайлОбъект, ХранениеВерсии);
ФайлОбъект.Записать();
РазблокироватьДанныеДляРедактирования(ФайлОбъект.Ссылка, УникальныйИдентификатор);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
// Находит максимальный номер версии для данного объекта Файл. Если нет версий - то 0.
// Параметры:
// ФайлСсылка - СправочникСсылка.Файлы - ссылка на файл.
//
// Возвращаемое значение:
// Число - максимальный номер версии.
//
Функция НайтиМаксимальныйНомерВерсии(ФайлСсылка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЕСТЬNULL(МАКСИМУМ(Версии.НомерВерсии), 0) КАК МаксимальныйНомер
|ИЗ
| Справочник.ВерсииФайлов КАК Версии
|ГДЕ
| Версии.Владелец = &Файл";
Запрос.Параметры.Вставить("Файл", ФайлСсылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Если Выборка.МаксимальныйНомер = Null Тогда
Возврат 0;
КонецЕсли;
Возврат Число(Выборка.МаксимальныйНомер);
КонецЕсли;
Возврат 0;
КонецФункции
// Вызывает исключение, если файл имеет недопустимый размер для загрузки.
Процедура ПроверитьРазмерФайлаДляЗагрузки(Файл) Экспорт
ОбщиеНастройки = РаботаСФайламиСлужебныйПовтИсп.НастройкиРаботыСФайлами().ОбщиеНастройки;
Если ТипЗнч(Файл) = Тип("Файл") Тогда
Размер = Файл.Размер();
Иначе
Размер = Файл.Размер;
КонецЕсли;
Если Размер > ОбщиеНастройки.МаксимальныйРазмерФайла Тогда
РазмерВМб = Размер / (1024 * 1024);
РазмерВМбМакс = ОбщиеНастройки.МаксимальныйРазмерФайла / (1024 * 1024);
Если ТипЗнч(Файл) = Тип("Файл") Тогда
Имя = Файл.Имя;
Иначе
Имя = ОбщегоНазначенияКлиентСервер.ПолучитьИмяСРасширением(
Файл.ПолноеНаименование, Файл.Расширение);
КонецЕсли;
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Размер файла ""%1"" (%2 Мб)
|превышает максимально допустимый размер файла (%3 Мб).'"),
Имя,
РаботаСФайламиСлужебныйКлиентСервер.ПолучитьСтрокуСРазмеромФайла(РазмерВМб),
РаботаСФайламиСлужебныйКлиентСервер.ПолучитьСтрокуСРазмеромФайла(РазмерВМбМакс));
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийФормыЭлементаФайла
// Параметры:
// Контекст - ФормаКлиентскогоПриложения:
// * Объект - ОпределяемыйТип.ПрисоединенныйФайлОбъект
//
Процедура ФормаЭлементаПриСозданииНаСервере(Контекст, Отказ, СтандартнаяОбработка, Параметры, ТолькоПросмотр, НастраиватьОбъектФормы = Ложь) Экспорт
Элементы = Контекст.Элементы;
КолонкиМассив = Новый Массив;
ТаблицаЭлектронныеПодписи = Контекст.РеквизитФормыВЗначение("ЭлектронныеПодписи"); // ТаблицаЗначений
Для Каждого ОписаниеКолонки Из ТаблицаЭлектронныеПодписи.Колонки Цикл
КолонкиМассив.Добавить(ОписаниеКолонки.Имя);
КонецЦикла;
Если ЗначениеЗаполнено(Параметры.ЗначениеКопирования) Тогда
ОбновлениеИнформационнойБазы.ПроверитьОбъектОбработан(Параметры.ЗначениеКопирования);
Если Параметры.РежимСоздания = "ИзШаблона" Тогда
ОбъектЗначение = ЗаполнитьДанныеФайлаПоШаблону(Контекст, Параметры, НастраиватьОбъектФормы)
Иначе
ОбъектЗначение = ЗаполнитьДанныеФайлаИзКопии(Контекст, Параметры, НастраиватьОбъектФормы);
КонецЕсли;
Иначе
Если ЗначениеЗаполнено(Параметры.ПрисоединенныйФайл) Тогда
ОбъектЗначение = Параметры.ПрисоединенныйФайл.ПолучитьОбъект();
Иначе
ОбъектЗначение = Параметры.Ключ.ПолучитьОбъект();
КонецЕсли;
ОбновлениеИнформационнойБазы.ПроверитьОбъектОбработан(ОбъектЗначение, Контекст);
КонецЕсли;
ОбъектЗначение.Заполнить(Неопределено);
МетаданныеСправочника = ОбъектЗначение.Метаданные(); // ОбъектМетаданныхСправочник
Контекст.ИмяСправочника = МетаданныеСправочника.Имя;
ВозможностьСоздаватьВерсииФайлов = ТипЗнч(ОбъектЗначение.Ссылка) = Тип("СправочникСсылка.Файлы");
Контекст.ВозможностьСоздаватьВерсииФайлов = ВозможностьСоздаватьВерсииФайлов;
Если НастраиватьОбъектФормы Тогда
Элементы.ХранитьВерсии0.Видимость = ВозможностьСоздаватьВерсииФайлов;
НастроитьОбъектФормы(ОбъектЗначение, Контекст);
Иначе
ЗначениеВДанныеФормы(ОбъектЗначение, Контекст.Объект);
Элементы.ХранитьВерсии.Видимость = ВозможностьСоздаватьВерсииФайлов;
КонецЕсли;
КриптографияПриСозданииФормыНаСервере(Контекст, Ложь);
ЗаполнитьСписокПодписей(Контекст, Параметры.ЗначениеКопирования);
ЗаполнитьСписокШифрования(Контекст, Параметры.ЗначениеКопирования);
ОбщиеНастройки = РаботаСФайламиСлужебныйПовтИсп.НастройкиРаботыСФайлами().ОбщиеНастройки;
РасширениеФайлаВСписке = РаботаСФайламиСлужебныйКлиентСервер.РасширениеФайлаВСписке(
ОбщиеНастройки.СписокРасширенийТекстовыхФайлов, Контекст.Объект.Расширение);
Если РасширениеФайлаВСписке Тогда
Если ВозможностьСоздаватьВерсииФайлов И Контекст.Объект.Свойство("ТекущаяВерсия") И ЗначениеЗаполнено(Контекст.Объект.ТекущаяВерсия) Тогда
ТекущаяВерсияФайла = Контекст.Объект.ТекущаяВерсия;
Иначе
ТекущаяВерсияФайла = Контекст.Объект.Ссылка;
КонецЕсли;
Если ЗначениеЗаполнено(ТекущаяВерсияФайла) Тогда
КодировкаЗначение = РегистрыСведений.КодировкиФайлов.КодировкаВерсииФайла(ТекущаяВерсияФайла);
СписокКодировок = Кодировки();
ЭлементСписка = СписокКодировок.НайтиПоЗначению(КодировкаЗначение);
Если ЭлементСписка = Неопределено Тогда
Контекст.Кодировка = КодировкаЗначение;
Иначе
Контекст.Кодировка = ЭлементСписка.Представление;
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(Контекст.Кодировка) Тогда
Контекст.Кодировка = НСтр("ru = 'По умолчанию'");
КонецЕсли;
Иначе
Контекст.Элементы.Кодировка.Видимость = Ложь;
КонецЕсли;
ЭтоСлужебныйФайл = Ложь;
Если ЕстьРеквизитСлужебный(Контекст.ИмяСправочника) Тогда
ЭтоСлужебныйФайл = ОбъектЗначение.Служебный;
КонецЕсли;
Если ЭтоСлужебныйФайл Тогда
Контекст.ТолькоПросмотр = Истина;
КонецЕсли;
Элементы.ФормаЗакрыть.Видимость = ЭтоСлужебныйФайл;
Элементы.ФормаЗакрыть.КнопкаПоУмолчанию = ЭтоСлужебныйФайл;
Элементы.ДекорацияПояснениеСлужебный.Видимость = ЭтоСлужебныйФайл;
Если ТипЗнч(Контекст.ТекущийПользователь) = Тип("СправочникСсылка.ВнешниеПользователи") Тогда
ИзменитьФормуДляВнешнегоПользователя(Контекст);
КонецЕсли;
Если ПолучитьФункциональнуюОпцию("ИспользоватьСинхронизациюФайлов") Тогда
Контекст.ФайлРедактируетсяВОблаке = ФайлРедактируетсяВОблаке(Контекст.Объект.Ссылка);
КонецЕсли;
Если ТолькоПросмотр
ИЛИ НЕ ПравоДоступа("Изменение", Контекст.Объект.Ссылка.Метаданные()) Тогда
УстановитьКнопкиИзмененияНевидимыми(Контекст.Элементы);
КонецЕсли;
Если НЕ ТолькоПросмотр
И НЕ Контекст.Объект.Ссылка.Пустая() И НастраиватьОбъектФормы Тогда
ЗаблокироватьДанныеДляРедактирования(Контекст.Объект.Ссылка, , Контекст.УникальныйИдентификатор);
КонецЕсли;
ТипВладельца = ТипЗнч(ОбъектЗначение.ВладелецФайла);
ЭлементВладелецФайла = Контекст.Элементы.ВладелецФайла; // ПолеФормы
ЭлементВладелецФайла.Заголовок = ТипВладельца;
КонецПроцедуры
Функция ЗаполнитьДанныеФайлаПоШаблону(Контекст, Параметры, НастраиватьОбъектФормы)
КопируемыйОбъект = Параметры.ЗначениеКопирования.ПолучитьОбъект();
Контекст.ЗначениеКопирования = Параметры.ЗначениеКопирования;
МенеджерСправочника = Справочники[Параметры.ИмяСправочникаХранилищаФайлов]; // СправочникМенеджер
ОбъектЗначение = МенеджерСправочника.СоздатьЭлемент();
ЗаполнитьЗначенияСвойств(
ОбъектЗначение,
КопируемыйОбъект,
"Наименование,
|Зашифрован,
|Описание,
|ПодписанЭП,
|Размер,
|Расширение,
|ВладелецФайла,
|ТекстХранилище,
|ПометкаУдаления");
ОбъектЗначение.ВладелецФайла = Параметры.ВладелецФайла;
ДатаСоздания = ТекущаяДатаСеанса();
ОбъектЗначение.ДатаСоздания = ДатаСоздания;
ОбъектЗначение.ДатаМодификацииУниверсальная = УниверсальноеВремя(ДатаСоздания);
ОбъектЗначение.Автор = Пользователи.АвторизованныйПользователь();
ОбъектЗначение.ТипХраненияФайла = ТипХраненияФайлов();
ОбъектЗначение.ХранитьВерсии = ?(Параметры.ИмяСправочникаХранилищаФайлов = "Файлы",
КопируемыйОбъект.ХранитьВерсии, Ложь);
Возврат ОбъектЗначение;
КонецФункции
Функция ЗаполнитьДанныеФайлаИзКопии(Контекст, Параметры, НастраиватьОбъектФормы)
КопируемыйОбъект = Параметры.ЗначениеКопирования.ПолучитьОбъект();
Контекст.ЗначениеКопирования = Параметры.ЗначениеКопирования;
ОбъектМетаданных = КопируемыйОбъект.Метаданные();
МенеджерСправочника = Справочники[ОбъектМетаданных.Имя]; // СправочникМенеджер
ОбъектЗначение = МенеджерСправочника.СоздатьЭлемент();
ИсключаемыеРеквизиты = "Родитель,Владелец,ДатаЗаема,Изменил,Код,ПометкаУдаления,Редактирует,Том,ИмяПредопределенныхДанных,Предопределенный,ПутьКФайлу,СтатусИзвлеченияТекста";
Если ОбъектМетаданных.Реквизиты.Найти("ТекущаяВерсия") <> Неопределено Тогда
ИсключаемыеРеквизиты = ИсключаемыеРеквизиты + ",ТекущаяВерсия";
КонецЕсли;
ЗаполнитьЗначенияСвойств(ОбъектЗначение,КопируемыйОбъект, , ИсключаемыеРеквизиты);
ОбъектЗначение.Автор = Пользователи.АвторизованныйПользователь();
ОбъектЗначение.ТипХраненияФайла = ТипХраненияФайлов();
Возврат ОбъектЗначение;
КонецФункции
Процедура НастроитьОбъектФормы(Знач НовыйОбъект, Контекст)
ТипНовогоОбъекта = Новый Массив;
ТипНовогоОбъекта.Добавить(ТипЗнч(НовыйОбъект));
НовыйРеквизит = Новый РеквизитФормы("Объект", Новый ОписаниеТипов(ТипНовогоОбъекта));
НовыйРеквизит.СохраняемыеДанные = Истина;
ДобавляемыеРеквизиты = Новый Массив;
ДобавляемыеРеквизиты.Добавить(НовыйРеквизит);
Контекст.ИзменитьРеквизиты(ДобавляемыеРеквизиты);
Контекст.ЗначениеВРеквизитФормы(НовыйОбъект, "Объект");
Для каждого Элемент Из Контекст.Элементы Цикл
Если ТипЗнч(Элемент) = Тип("ПолеФормы")
И СтрНачинаетсяС(Элемент.ПутьКДанным, "ОбъектПрототип[0].")
И СтрЗаканчиваетсяНа(Элемент.Имя, "0") Тогда
ИмяЭлемента = Лев(Элемент.Имя, СтрДлина(Элемент.Имя) -1);
Если Контекст.Элементы.Найти(ИмяЭлемента) <> Неопределено Тогда
Продолжить;
КонецЕсли;
НовыйЭлемент = Контекст.Элементы.Вставить(ИмяЭлемента, ТипЗнч(Элемент), Элемент.Родитель, Элемент);
НовыйЭлемент.ПутьКДанным = "Объект." + Сред(Элемент.ПутьКДанным, СтрДлина("ОбъектПрототип[0].") + 1);
Если Элемент.Вид = ВидПоляФормы.ПолеФлажка Или Элемент.Вид = ВидПоляФормы.ПолеКартинки Тогда
ИсключаемыеСвойства = "Имя, ПутьКДанным";
Иначе
ИсключаемыеСвойства = "Имя, ПутьКДанным, ВыделенныйТекст, СвязьПоТипу";
КонецЕсли;
ЗаполнитьЗначенияСвойств(НовыйЭлемент, Элемент, , ИсключаемыеСвойства);
Элемент.Видимость = Ложь;
КонецЕсли;
КонецЦикла;
Если Не НовыйОбъект.ЭтоНовый() Тогда
Контекст.НавигационнаяСсылка = ПолучитьНавигационнуюСсылку(НовыйОбъект);
КонецЕсли;
КонецПроцедуры
Процедура ЗаполнитьСписокШифрования(Контекст, Знач Источник = Неопределено) Экспорт
Если Не ЗначениеЗаполнено(Источник) Тогда
Источник = Контекст.Объект;
КонецЕсли;
Контекст.СертификатыШифрования.Очистить();
Если Источник.Зашифрован Тогда
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
СертификатыШифрования = МодульЭлектроннаяПодпись.СертификатыШифрования(Источник.Ссылка);
Для Каждого СертификатШифрования Из СертификатыШифрования Цикл
НоваяСтрока = Контекст.СертификатыШифрования.Добавить();
НоваяСтрока.Представление = СертификатШифрования.Представление;
НоваяСтрока.Отпечаток = СертификатШифрования.Отпечаток;
НоваяСтрока.ПорядковыйНомер = СертификатШифрования.ПорядковыйНомер;
ДвоичныеДанныеСертификата = СертификатШифрования.Сертификат;
Если ДвоичныеДанныеСертификата <> Неопределено Тогда
НоваяСтрока.АдресСертификата = ПоместитьВоВременноеХранилище(
ДвоичныеДанныеСертификата, Контекст.УникальныйИдентификатор);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
ТекстЗаголовка = НСтр("ru = 'Разрешено расшифровывать'");
Если Контекст.СертификатыШифрования.Количество() <> 0 Тогда
ТекстЗаголовка =ТекстЗаголовка + " (" + Формат(Контекст.СертификатыШифрования.Количество(), "ЧГ=") + ")";
КонецЕсли;
ГруппаСертификатыШифрования = Контекст.Элементы.ГруппаСертификатыШифрования; // ГруппаФормы
ГруппаСертификатыШифрования.Заголовок = ТекстЗаголовка;
КонецПроцедуры
Процедура ЗаполнитьСписокПодписей(Контекст, Знач Источник = Неопределено) Экспорт
Если Не ЗначениеЗаполнено(Источник) Тогда
Источник = Контекст.Объект;
КонецЕсли;
Контекст.ЭлектронныеПодписи.Очистить();
ЭлектронныеПодписи = СписокЭлектронныхПодписей(Источник, Контекст.УникальныйИдентификатор);
Для Каждого ЭлектроннаяПодписьФайла Из ЭлектронныеПодписи Цикл
НоваяСтрока = Контекст.ЭлектронныеПодписи.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ЭлектроннаяПодписьФайла);
РаботаСФайламиСлужебныйКлиентСервер.ЗаполнитьСтатусПодписи(НоваяСтрока);
ДвоичныеДанныеСертификата = ЭлектроннаяПодписьФайла.Сертификат.Получить();
Если ДвоичныеДанныеСертификата <> Неопределено Тогда
НоваяСтрока.АдресСертификата = ПоместитьВоВременноеХранилище(
ДвоичныеДанныеСертификата, Контекст.УникальныйИдентификатор);
КонецЕсли;
КонецЦикла;
ТекстЗаголовка = НСтр("ru = 'Электронные подписи'");
Если Контекст.ЭлектронныеПодписи.Количество() <> 0 Тогда
ТекстЗаголовка = ТекстЗаголовка + " (" + Строка(Контекст.ЭлектронныеПодписи.Количество()) + ")";
КонецЕсли;
ГруппаЭлектронныеПодписи = Контекст.Элементы.ГруппаЭлектронныеПодписи; // ГруппаФормы
ГруппаЭлектронныеПодписи.Заголовок = ТекстЗаголовка;
КонецПроцедуры
Функция СписокЭлектронныхПодписей(Источник, УникальныйИдентификатор)
ЭлектронныеПодписи = Новый Массив;
Если Источник.ПодписанЭП Тогда
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
ЭлектронныеПодписи = МодульЭлектроннаяПодпись.УстановленныеПодписи(Источник.Ссылка);
Для Каждого ЭлектроннаяПодписьФайла Из ЭлектронныеПодписи Цикл
ЭлектроннаяПодписьФайла.Вставить("Объект", Источник.Ссылка);
АдресПодписи = ПоместитьВоВременноеХранилище(ЭлектроннаяПодписьФайла.Подпись, УникальныйИдентификатор);
ЭлектроннаяПодписьФайла.Вставить("АдресПодписи", АдресПодписи);
КонецЦикла;
КонецЕсли;
КонецЕсли;
Возврат ЭлектронныеПодписи;
КонецФункции
Функция СписокПодписейДляОтправки(Источник, УникальныйИдентификатор, ИмяФайла)
ЭлектронныеПодписи = Новый Массив;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
ЭлектронныеПодписи = СписокЭлектронныхПодписей(Источник, УникальныйИдентификатор);
СоставИмениФайлаДанных = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(ИмяФайла);
МодульЭлектроннаяПодписьСлужебныйКлиентСервер = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебныйКлиентСервер");
МодульЭлектроннаяПодписьСлужебный = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодписьСлужебный");
МодульЭлектроннаяПодпись = ОбщегоНазначения.ОбщийМодуль("ЭлектроннаяПодпись");
РасширениеДляФайловПодписи = МодульЭлектроннаяПодпись.ПерсональныеНастройки().РасширениеДляФайловПодписи;
Для Каждого ЭлектроннаяПодписьФайла Из ЭлектронныеПодписи Цикл
ИмяФайлаПодписи = МодульЭлектроннаяПодписьСлужебныйКлиентСервер.ИмяФайлаПодписи(СоставИмениФайлаДанных.ИмяБезРасширения,
Строка(ЭлектроннаяПодписьФайла.КомуВыданСертификат), РасширениеДляФайловПодписи);
ЭлектроннаяПодписьФайла.Вставить("ИмяФайла", ИмяФайлаПодписи);
ДанныеПоСертификату = МодульЭлектроннаяПодписьСлужебный.ДанныеПоСертификату(ЭлектроннаяПодписьФайла, УникальныйИдентификатор);
ЭлектроннаяПодписьФайла.Вставить("АдресСертификата", ДанныеПоСертификату.АдресСертификата);
ИмяФайлаСертификата = МодульЭлектроннаяПодписьСлужебныйКлиентСервер.ИмяФайлаСертификата(СоставИмениФайлаДанных.ИмяБезРасширения,
Строка(ЭлектроннаяПодписьФайла.КомуВыданСертификат), ДанныеПоСертификату.РасширениеСертификата);
ЭлектроннаяПодписьФайла.Вставить("ИмяФайлаСертификата", ИмяФайлаСертификата);
КонецЦикла;
КонецЕсли;
Возврат ЭлектронныеПодписи;
КонецФункции
Процедура УстановитьКнопкиИзмененияНевидимыми(Элементы)
ИменаКоманд = ПолучитьИменаКомандИзмененияОбъекта();
Для каждого ЭлементФормы Из Элементы Цикл
Если ТипЗнч(ЭлементФормы) <> Тип("КнопкаФормы") Тогда
Продолжить;
КонецЕсли;
Если ИменаКоманд.Найти(ЭлементФормы.ИмяКоманды) <> Неопределено Тогда
ЭлементФормы.Видимость = Ложь;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ПолучитьИменаКомандИзмененияОбъекта()
ИменаКоманд = Новый Массив;
ИменаКоманд.Добавить("ПодписатьФайлЭП");
ИменаКоманд.Добавить("ДобавитьЭПИзФайла");
ИменаКоманд.Добавить("УдалитьЭП");
ИменаКоманд.Добавить("Редактировать");
ИменаКоманд.Добавить("СохранитьИзменения");
ИменаКоманд.Добавить("ЗакончитьРедактирование");
ИменаКоманд.Добавить("Освободить");
ИменаКоманд.Добавить("Зашифровать");
ИменаКоманд.Добавить("Расшифровать");
ИменаКоманд.Добавить("СтандартныеСкопировать");
ИменаКоманд.Добавить("ОбновитьИзФайлаНаДиске");
ИменаКоманд.Добавить("СтандартнаяЗаписать");
ИменаКоманд.Добавить("СтандартнаяЗаписатьИЗакрыть");
ИменаКоманд.Добавить("СтандартныеУстановитьПометкуУдаления");
Возврат ИменаКоманд;
КонецФункции
Функция НастройкиФайлов() Экспорт
НастройкиФайлов = Новый Структура;
НастройкиФайлов.Вставить("НеОчищатьФайлы", Новый Массив);
НастройкиФайлов.Вставить("НеСинхронизироватьФайлы", Новый Массив);
НастройкиФайлов.Вставить("НеВыводитьВИнтерфейс", Новый Массив);
НастройкиФайлов.Вставить("НеСоздаватьФайлыПоШаблону", Новый Массив);
НастройкиФайлов.Вставить("ФайлыБезПапок", Новый Массив);
ИнтеграцияПодсистемБСП.ПриОпределенииОбъектовИсключенияСинхронизацииФайлов(НастройкиФайлов.НеСинхронизироватьФайлы);
РаботаСФайламиПереопределяемый.ПриОпределенииНастроек(НастройкиФайлов);
Возврат НастройкиФайлов;
КонецФункции
// Параметры:
// Результат - Массив из см. ОписаниеФайла
//
Процедура СформироватьСписокФайловДляОтправкиПоПочте(Результат, ФайлВложение, ИдентификаторФормы) Экспорт
ДанныеФайлаИДвоичныеДанные = РаботаСФайлами.ДанныеФайла(ФайлВложение, ИдентификаторФормы); // см. РаботаСФайлами.ДанныеФайла
ИмяФайла = ОбщегоНазначенияКлиентСервер.ПолучитьИмяСРасширением(
ДанныеФайлаИДвоичныеДанные.Наименование, ДанныеФайлаИДвоичныеДанные.Расширение);
ОписаниеФайла = ОписаниеФайла(ИмяФайла, ДанныеФайлаИДвоичныеДанные.СсылкаНаДвоичныеДанныеФайла);
Результат.Добавить(ОписаниеФайла);
Если ФайлВложение.ПодписанЭП Тогда
СписокПодписей = СписокПодписейДляОтправки(ФайлВложение, ИдентификаторФормы, ИмяФайла);
Для каждого ЭлектроннаяПодписьФайла Из СписокПодписей Цикл
ОписаниеФайла = ОписаниеФайла(ЭлектроннаяПодписьФайла.ИмяФайла, ЭлектроннаяПодписьФайла.АдресПодписи);
Результат.Добавить(ОписаниеФайла);
Если ЗначениеЗаполнено(ЭлектроннаяПодписьФайла.АдресСертификата) Тогда
ОписаниеФайла = ОписаниеФайла(ЭлектроннаяПодписьФайла.ИмяФайлаСертификата, ЭлектроннаяПодписьФайла.АдресСертификата);
Результат.Добавить(ОписаниеФайла);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Функция ОписаниеФайла(ИмяФайла, АдресВоВременномХранилище)
ОписаниеФайла = Новый Структура;
ОписаниеФайла.Вставить("Представление", ИмяФайла);
ОписаниеФайла.Вставить("АдресВоВременномХранилище", АдресВоВременномХранилище);
Возврат ОписаниеФайла;
КонецФункции
#КонецОбласти
#Область ОчисткаНенужныхФайлов
// Параметры:
// НастройкаОчистки - СтрокаТаблицыЗначений:
// * ВладелецФайла - ОпределяемыйТип.ПрисоединенныйФайл
// * ИдентификаторВладельца - СправочникСсылка.ИдентификаторыОбъектовМетаданных
// * ЭтоНастройкаДляЭлементаСправочника - Булево
// * ТипВладельцаФайла - СправочникСсылка.ИдентификаторыОбъектовМетаданных
// * ПравилоОтбора - ХранилищеЗначения
// * Действие - ПеречислениеСсылка.ВариантыОчисткиФайлов
// * ПериодОчистки - ПеречислениеСсылка.ПериодОчисткиФайлов
// * ЭтоФайл - Булево
//
Процедура ОчиститьДанныеНенужныхФайлов(НастройкаОчистки, МассивИсключений = Неопределено)
Если НастройкаОчистки.Действие = Перечисления.ВариантыОчисткиФайлов.НеОчищать Тогда
Возврат;
КонецЕсли;
Если МассивИсключений = Неопределено Тогда
МассивИсключений = Новый Массив;
КонецЕсли;
ДеревоВладельцев = ВыбратьДанныеПоПравилу(НастройкаОчистки, МассивИсключений);
Если ДеревоВладельцев.Строки.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Для Каждого Файл Из ДеревоВладельцев.Строки Цикл
Если НастройкаОчистки.ЭтоФайл Тогда
Если НастройкаОчистки.Действие = Перечисления.ВариантыОчисткиФайлов.ОчиститьФайлыИВерсии Тогда
ФайлДляПометки = Файл.ФайлСсылка.ПолучитьОбъект();
// Пропускаем удаление, если файл занят для редактирования.
Если ЗначениеЗаполнено(ФайлДляПометки.Редактирует) Тогда
Продолжить;
КонецЕсли;
ФайлДляПометки.УстановитьПометкуУдаления(Истина);
КонецЕсли;
Для Каждого Версия Из Файл.Строки Цикл
ВыполнитьОчисткуДанныхОВерсии(Версия.ВерсияСсылка);
КонецЦикла;
Иначе
ВыполнитьОчисткуДанныхОФайле(Файл.ФайлСсылка);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ВыбратьДанныеПоПравилу(НастройкаОчистки, МассивИсключений)
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
ОчищатьПоПравилу = НастройкаОчистки.ПериодОчистки = Перечисления.ПериодОчисткиФайлов.ПоПравилу;
Если ОчищатьПоПравилу Тогда
НастройкиКомпоновщика = НастройкаОчистки.ПравилоОтбора.Получить();
Если НастройкиКомпоновщика <> Неопределено Тогда
КомпоновщикНастроек.ЗагрузитьНастройки(НастройкаОчистки.ПравилоОтбора.Получить());
КонецЕсли;
КонецЕсли;
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
ИсточникДанных = СхемаКомпоновкиДанных.ИсточникиДанных.Добавить();
ИсточникДанных.Имя = "ИсточникДанных1";
ИсточникДанных.ТипИсточникаДанных = "Local";
НаборДанных = СхемаКомпоновкиДанных.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанных.Имя = "НаборДанных1";
НаборДанных.ИсточникДанных = ИсточникДанных.Имя;
СхемаКомпоновкиДанных.ПоляИтога.Очистить();
Если НастройкаОчистки.ЭтоНастройкаДляЭлементаСправочника Тогда
ВладелецФайла = НастройкаОчистки.ИдентификаторВладельца;
ЭлементИсключение = НастройкаОчистки.ВладелецФайла;
Иначе
ВладелецФайла = НастройкаОчистки.ВладелецФайла;
ЭлементИсключение = Неопределено;
КонецЕсли;
СхемаКомпоновкиДанных.НаборыДанных[0].Запрос = ТекстЗапросаДляОчисткиФайлов(
ВладелецФайла,
НастройкаОчистки,
МассивИсключений,
ЭлементИсключение);
Структура = КомпоновщикНастроек.Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ФайлСсылка");
Если НастройкаОчистки.ЭтоФайл Тогда
СтруктураВерсий = Структура.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
ВыбранноеПоле = СтруктураВерсий.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ВерсияСсылка");
КонецЕсли;
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));
Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ТипВладельца");
Параметр.Значение = ТипЗнч(ВладелецФайла.ЗначениеПустойСсылки);
Параметр.Использование = Истина;
Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ПериодОчистки");
Если Параметр <> Неопределено Тогда
Если НастройкаОчистки.ПериодОчистки = Перечисления.ПериодОчисткиФайлов.СтаршеМесяца Тогда
ЗначениеПериодаОчистки = ДобавитьМесяц(НачалоДня(ТекущаяДатаСеанса()), -1);
ИначеЕсли НастройкаОчистки.ПериодОчистки = Перечисления.ПериодОчисткиФайлов.СтаршеГода Тогда
ЗначениеПериодаОчистки = ДобавитьМесяц(НачалоДня(ТекущаяДатаСеанса()), -12);
ИначеЕсли НастройкаОчистки.ПериодОчистки = Перечисления.ПериодОчисткиФайлов.СтаршеШестиМесяцев Тогда
ЗначениеПериодаОчистки = ДобавитьМесяц(НачалоДня(ТекущаяДатаСеанса()), -6);
КонецЕсли;
Параметр.Значение = ЗначениеПериодаОчистки;
Параметр.Использование = Истина;
КонецЕсли;
ПараметрТекущаяДата = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ТекущаяДата");
Если ПараметрТекущаяДата <> Неопределено Тогда
ПараметрТекущаяДата.Значение = ТекущаяДатаСеанса();
ПараметрТекущаяДата.Использование = Истина;
КонецЕсли;
Если МассивИсключений.Количество() > 0 Тогда
Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("МассивИсключений");
Параметр.Значение = МассивИсключений;
Параметр.Использование = Истина;
КонецЕсли;
Если НастройкаОчистки.ЭтоНастройкаДляЭлементаСправочника Тогда
Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ЭлементИсключение");
Параметр.Значение = ЭлементИсключение;
Параметр.Использование = Истина;
КонецЕсли;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ДеревоЗначений = Новый ДеревоЗначений;
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных);
ПроцессорВывода.УстановитьОбъект(ДеревоЗначений);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
Возврат ДеревоЗначений;
КонецФункции
#КонецОбласти
#Область СинхронизацияФайлов
// Возвращаемое значение:
// ТаблицаЗначений:
// * Ссылка - СправочникСсылка.УчетныеЗаписиСинхронизацииФайлов
// * Сервис - Строка
//
Функция УчетныеЗаписиСинхронизации()
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ
| УчетныеЗаписиСинхронизацииФайлов.Ссылка,
| УчетныеЗаписиСинхронизацииФайлов.Сервис
|ИЗ
| РегистрСведений.НастройкиСинхронизацииФайлов КАК НастройкиСинхронизацииФайлов
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.УчетныеЗаписиСинхронизацииФайлов КАК УчетныеЗаписиСинхронизацииФайлов
| ПО НастройкиСинхронизацииФайлов.УчетнаяЗапись = УчетныеЗаписиСинхронизацииФайлов.Ссылка
|ГДЕ
| НЕ УчетныеЗаписиСинхронизацииФайлов.ПометкаУдаления
| И НастройкиСинхронизацииФайлов.Синхронизировать";
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Процедура УстановитьПараметрРегламентногоЗаданияСинхронизацииФайлов(Знач ИмяПараметра, Знач ЗначениеПараметра) Экспорт
ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить("Метаданные", Метаданные.РегламентныеЗадания.СинхронизацияФайлов);
Если Не ОбщегоНазначения.РазделениеВключено() Тогда
ПараметрыЗадания.Вставить("ИмяМетода", Метаданные.РегламентныеЗадания.СинхронизацияФайлов.ИмяМетода);
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
СписокЗаданий = РегламентныеЗаданияСервер.НайтиЗадания(ПараметрыЗадания);
Если СписокЗаданий.Количество() = 0 Тогда
ПараметрыЗадания.Вставить(ИмяПараметра, ЗначениеПараметра);
РегламентныеЗаданияСервер.ДобавитьЗадание(ПараметрыЗадания);
Иначе
ПараметрыЗадания = Новый Структура(ИмяПараметра, ЗначениеПараметра);
Для Каждого Задание Из СписокЗаданий Цикл
РегламентныеЗаданияСервер.ИзменитьЗадание(Задание, ПараметрыЗадания);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Функция ЭтоПапкаФайлов(ОбъектВладелец) Экспорт
Возврат ТипЗнч(ОбъектВладелец) = Тип("СправочникСсылка.ПапкиФайлов");
КонецФункции
Функция ФайлРедактируетсяВОблаке(Файл)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| СтатусыСинхронизацииФайловСОблачнымСервисом.Файл
|ИЗ
| РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
|ГДЕ
| СтатусыСинхронизацииФайловСОблачнымСервисом.Файл = &Файл";
Запрос.УстановитьПараметр("Файл", Файл);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Возврат Истина;
КонецЦикла;
Возврат Ложь;
КонецФункции
Функция ПриОпределенииОбъектовИсключенияСинхронизацииФайлов() Экспорт
Возврат НастройкиФайлов().НеСинхронизироватьФайлы;
КонецФункции
Функция ТекстЗапросаДляСинхронизацииФайлов(ВладелецФайла, НастройкаСинхронизации, МассивИсключений, ЭлементИсключение)
ТипОбъекта = ВладелецФайла;
ПредставлениеТипаВладельца = ОбщегоНазначения.ВидОбъектаПоТипу(ТипЗнч(ТипОбъекта.ЗначениеПустойСсылки));
ПолноеИмяСправочникаФайлов = НастройкаСинхронизации.ТипВладельцаФайла.ПолноеИмя;
МетаданныеОбъектаФайлов = Метаданные.НайтиПоПолномуИмени(ПолноеИмяСправочникаФайлов);
ЕстьВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", МетаданныеОбъектаФайлов);
ТекстЗапроса = "";
СправочникФайлов = ОбщегоНазначения.ОбъектМетаданныхПоИдентификатору(НастройкаСинхронизации.ТипВладельцаФайла, Ложь);
Если ТипЗнч(СправочникФайлов) <> Тип("ОбъектМетаданных") Тогда
Возврат "";
КонецЕсли;
ВозможностьСоздаватьГруппы = СправочникФайлов.Иерархический;
Если ТипЗнч(ВладелецФайла) <> Тип("СправочникСсылка.ИдентификаторыОбъектовМетаданных") Тогда
СправочникПапок = ОбщегоНазначения.ОбъектМетаданныхПоИдентификатору(НастройкаСинхронизации.ИдентификаторВладельца, Ложь);
Иначе
СправочникПапок = ОбщегоНазначения.ОбъектМетаданныхПоИдентификатору(ВладелецФайла, Ложь);
КонецЕсли;
Если ТипЗнч(СправочникПапок) <> Тип("ОбъектМетаданных") Тогда
Возврат "";
КонецЕсли;
Если Не ПустаяСтрока(ТекстЗапроса) Тогда
ТекстЗапроса= ТекстЗапроса + "
|
|ОБЪЕДИНИТЬ ВСЕ
|";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "ВЫБРАТЬ
| СправочникПапок.Ссылка,";
ДобавитьДоступныеПоляОтбора(ТекстЗапроса, ТипОбъекта);
ТекстЗапроса = ТекстЗапроса + "
| СправочникФайлов.Ссылка КАК ФайлСсылка,";
Если ВозможностьСоздаватьГруппы Тогда
ТекстЗапроса = ТекстЗапроса + "
| ВЫБОР Когда СправочникФайлов.ЭтоГруппа Тогда
| СправочникФайлов.Наименование
| ИНАЧЕ
| СправочникФайлов.Наименование + ""."" + СправочникФайлов.Расширение
| КОНЕЦ КАК Наименование,
| СправочникФайлов.ПометкаУдаления КАК ПометкаУдаления,
| СправочникФайлов.ВладелецФайла КАК Родитель,
| ЛОЖЬ КАК ЭтоПапка,";
ОтборПоПапкам = "(СправочникФайлов.ЭтоГруппа
| ИЛИ (НЕ СправочникФайлов.ЭтоГруппа И СправочникФайлов.ПодписанЭП = ЛОЖЬ И СправочникФайлов.Зашифрован = ЛОЖЬ)) ";
Иначе
ТекстЗапроса = ТекстЗапроса + "
| СправочникФайлов.Наименование + ""."" + СправочникФайлов.Расширение КАК Наименование,
| СправочникФайлов.ПометкаУдаления КАК ПометкаУдаления,
| СправочникФайлов.ВладелецФайла КАК Родитель,
| ЛОЖЬ КАК ЭтоПапка,";
ОтборПоПапкам = " СправочникФайлов.ПодписанЭП = ЛОЖЬ И СправочникФайлов.Зашифрован = ЛОЖЬ ";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
| ИСТИНА КАК ЕстьВБазе,
| ЛОЖЬ КАК ЕстьНаСервере,
| НЕОПРЕДЕЛЕНО КАК Изменения,
| ЕСТЬNULL(СтатусыСинхронизацииФайловСОблачнымСервисом.Href, """") КАК Href,
| ЕСТЬNULL(СтатусыСинхронизацииФайловСОблачнымСервисом.Etag, """") КАК Etag,
| ЛОЖЬ КАК Обработан,
| ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0) КАК ДатаСинхронизации,
| ВЫРАЗИТЬ("""" КАК СТРОКА(36)) КАК UID1C,
| """" КАК ToHref,
| """" КАК ToEtag,
| """" КАК РодительСервер,
| """" КАК НаименованиеСервер,
| ЛОЖЬ КАК ИзмененНаСервере,
| НЕОПРЕДЕЛЕНО КАК Уровень,
| """" КАК РодительСортировка,
| " + ?(ЕстьВозможностьХранитьВерсии, "ИСТИНА", "ЛОЖЬ") + " КАК ЭтоФайл
|ИЗ
| Справочник." + СправочникФайлов.Имя + " КАК СправочникФайлов
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
| ПО (СтатусыСинхронизацииФайловСОблачнымСервисом.Файл = СправочникФайлов.Ссылка)
| ЛЕВОЕ СОЕДИНЕНИЕ " + ПредставлениеТипаВладельца+ "." + СправочникПапок.Имя + " КАК СправочникПапок
| ПО (СправочникФайлов.ВладелецФайла = СправочникПапок.Ссылка)
|ГДЕ
| " + ОтборПоПапкам + " И ТИПЗНАЧЕНИЯ(СправочникФайлов.ВладелецФайла) = &ТипВладельца";
Если МассивИсключений.Количество() > 0 Тогда
ТекстЗапроса = ТекстЗапроса + "
| И НЕ СправочникПапок.Ссылка В ИЕРАРХИИ (&МассивИсключений)";
КонецЕсли;
Если ЭлементИсключение <> Неопределено Тогда
ТекстЗапроса = ТекстЗапроса + "
| И СправочникПапок.Ссылка В ИЕРАРХИИ (&ЭлементИсключение)";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| СправочникПапок.Ссылка,";
ДобавитьДоступныеПоляОтбора(ТекстЗапроса, ТипОбъекта);
ТекстЗапроса = ТекстЗапроса + "
| СправочникПапок.Ссылка,
| " + ?(ПредставлениеТипаВладельца = "Документ",
"СправочникПапок.Представление", "СправочникПапок.Наименование") + ",
| СправочникПапок.ПометкаУдаления,";
Если ОбщегоНазначения.ЭтоСправочник(СправочникПапок) И СправочникПапок.Иерархический Тогда
ТекстЗапроса = ТекстЗапроса + "
| ВЫБОР
| КОГДА СправочникПапок.Родитель = ЗНАЧЕНИЕ(Справочник." + СправочникПапок.Имя + ".ПустаяСсылка)
| ТОГДА НЕОПРЕДЕЛЕНО
| ИНАЧЕ СправочникПапок.Родитель
| КОНЕЦ,";
Иначе
ТекстЗапроса = ТекстЗапроса + "Неопределено,";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "
| ИСТИНА,
| ИСТИНА,
| ЛОЖЬ,
| НЕОПРЕДЕЛЕНО,
| ЕСТЬNULL(СтатусыСинхронизацииФайловСОблачнымСервисом.Href, """"),
| """",
| ЛОЖЬ,
| ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0),
| """",
| """",
| """",
| """",
| """",
| ЛОЖЬ,
| НЕОПРЕДЕЛЕНО,
| """",
| " + ?(ЕстьВозможностьХранитьВерсии, "ИСТИНА", "ЛОЖЬ") + "
|ИЗ
| " + ПредставлениеТипаВладельца + "." + СправочникПапок.Имя + " КАК СправочникПапок
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
| ПО (СтатусыСинхронизацииФайловСОблачнымСервисом.Файл = СправочникПапок.Ссылка
| И СтатусыСинхронизацииФайловСОблачнымСервисом.УчетнаяЗапись = &УчетнаяЗапись)
| ГДЕ
| ИСТИНА";
Если МассивИсключений.Количество() > 0 Тогда
ТекстЗапроса = ТекстЗапроса + "
| И НЕ СправочникПапок.Ссылка В ИЕРАРХИИ (&МассивИсключений)";
КонецЕсли;
Если ЭлементИсключение <> Неопределено Тогда
ТекстЗапроса = ТекстЗапроса + "
| И СправочникПапок.Ссылка В ИЕРАРХИИ (&ЭлементИсключение)";
КонецЕсли;
Возврат ТекстЗапроса;
КонецФункции
Функция ЭтоВладелецФайлов(ОбъектВладелец)
МассивТиповФайлов = Метаданные.ОпределяемыеТипы.ВладелецПрисоединенныхФайлов.Тип.Типы();
Возврат МассивТиповФайлов.Найти(ТипЗнч(ОбъектВладелец)) <> Неопределено;
КонецФункции
// Параметры:
// ТипОбъекта - ОбъектМетаданныхСправочник
//
Процедура ДобавитьДоступныеПоляОтбора(ТекстЗапроса, ТипОбъекта)
ВсеСправочники = Справочники.ТипВсеСсылки();
ВсеДокументы = Документы.ТипВсеСсылки();
Если ВсеСправочники.СодержитТип(ТипЗнч(ТипОбъекта.ЗначениеПустойСсылки)) Тогда
Справочник = Метаданные.Справочники[ТипОбъекта.Имя];
Для Каждого Реквизит Из Справочник.Реквизиты Цикл
ТекстЗапроса = ТекстЗапроса + Символы.ПС + "СправочникПапок." + Реквизит.Имя + " КАК " + Реквизит.Имя +",";
КонецЦикла;
ИначеЕсли ВсеДокументы.СодержитТип(ТипЗнч(ТипОбъекта.ЗначениеПустойСсылки)) Тогда
Документ = Метаданные.Документы[ТипОбъекта.Имя];
Для Каждого Реквизит Из Документ.Реквизиты Цикл
Если Реквизит.Тип.СодержитТип(Тип("Дата")) Тогда
ТекстЗапроса = ТекстЗапроса + Символы.ПС + "РАЗНОСТЬДАТ(" + Реквизит.Имя + ", &ТекущаяДата, ДЕНЬ) Как ДнейДоУдаленияОт" + Реквизит.Имя + ",";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + Символы.ПС + "СправочникПапок." + Реквизит.Имя + ",";
КонецЦикла;
КонецЕсли;
КонецПроцедуры
// Проверяет, была ли ошибка при выполнении HTTP запроса, и вызывает соответствующее исключение.
Функция ПроверитьИсключениеHTTP1С(Ответ, АдресСервера)
Результат = Новый Структура("Успешно, ТекстОшибки, КодОшибки");
Если (Ответ.КодСостояния >= 400) И (Ответ.КодСостояния <= 599) Тогда
ШаблонОшибки = НСтр("ru = 'Не удалось синхронизировать файл по адресу %2, т.к. сервер вернул HTTP код: %1. %3'");
ИнформацияОбОшибке = Ответ.ПолучитьТелоКакСтроку();
Результат.Успешно = Ложь;
Результат.КодОшибки = Ответ.КодСостояния;
Результат.ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонОшибки,
Ответ.КодСостояния, РаскодироватьСтроку(АдресСервера, СпособКодированияСтроки.URLВКодировкеURL), ИнформацияОбОшибке);
Возврат Результат;
КонецЕсли;
Результат.Успешно = Истина;
Возврат Результат;
КонецФункции
// Выполняет метод протокола webdav.
Функция ВыполнитьМетодWebdav(ИмяМетода, АдресФайлаHRef, СоответствиеЗаголовков, СтруктураОбмена, XMLЗапрос="", ТекстПротокола = Неопределено)
СтруктураHref = СтруктураURIРаскодированная(АдресФайлаHRef);
Соединение = СоздатьHTTPСоединениеWebdav(СтруктураHref, СтруктураОбмена, 20);
HTTPЗапросWebdav = Новый HTTPЗапрос(СтруктураHref.ПутьНаСервере, СоответствиеЗаголовков);
Если ЗначениеЗаполнено(XMLЗапрос) Тогда
HTTPЗапросWebdav.УстановитьТелоИзСтроки(XMLЗапрос);
КонецЕсли;
Если ТекстПротокола <> Неопределено Тогда
ТекстПротокола = ТекстПротокола + ?(ПустаяСтрока(ТекстПротокола), "", Символы.ПС)
+ ИмяМетода + " " + АдресФайлаHRef + Символы.ПС + Символы.ПС + XMLЗапрос + Символы.ПС;
КонецЕсли;
ВызватьМетодHTTP(СтруктураОбмена, Соединение, ИмяМетода, HTTPЗапросWebdav);
Если ТекстПротокола <> Неопределено Тогда
ТекстПротокола = ТекстПротокола + ?(ПустаяСтрока(ТекстПротокола), "", Символы.ПС) + "HTTP RESPONSE "
+ СтруктураОбмена.Ответ.КодСостояния + Символы.ПС + Символы.ПС;
Для каждого ЗаголовокОтвета Из СтруктураОбмена.Ответ.Заголовки Цикл
ТекстПротокола = ТекстПротокола+ЗаголовокОтвета.Ключ + ": " + ЗаголовокОтвета.Значение + Символы.ПС;
КонецЦикла;
ТекстПротокола = ТекстПротокола + Символы.ПС + СтруктураОбмена.Ответ.ПолучитьТелоКакСтроку() + Символы.ПС;
КонецЕсли;
Возврат ПроверитьИсключениеHTTP1С(СтруктураОбмена.Ответ, АдресФайлаHRef);
КонецФункции
Процедура ВызватьМетодHTTP(СтруктураОбмена, Соединение, ИмяМетода, HTTPЗапросWebdav, ТекущаяПопытка = 1)
СтруктураОбмена.Ответ = Соединение.ВызватьHTTPМетод(ИмяМетода, HTTPЗапросWebdav);
Если СтруктураОбмена.Ответ.КодСостояния = 429
И ТекущаяПопытка <= 5 Тогда
ТекущееВремя = ТекущаяДатаСеанса();
ВремяОжидания = ТекущееВремя + 2;
Пока ТекущееВремя <= ВремяОжидания Цикл
ТекущееВремя = ТекущаяДатаСеанса();
КонецЦикла;
ВызватьМетодHTTP(СтруктураОбмена, Соединение, ИмяМетода, HTTPЗапросWebdav, ТекущаяПопытка + 1)
КонецЕсли;
КонецПроцедуры
// Обновляет уникальный служебный реквизит файла на сервере webdav.
Функция ОбновитьUID1CФайла(АдресФайлаHRef, UID1C, ПараметрыСинхронизации)
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
ЗаголовкиHTTP["Content-type"] = "text/xml";
ЗаголовкиHTTP["Accept"] = "text/xml";
XMLЗапрос = "<?xml version=""1.0"" encoding=""utf-8""?>
|<D:propertyupdate xmlns:D=""DAV:"" xmlns:U=""tsov.pro"">
| <D:set><D:prop>
| <U:UID1C>%1</U:UID1C>
| </D:prop></D:set>
|</D:propertyupdate>";
XMLЗапрос = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(XMLЗапрос, UID1C);
Возврат ВыполнитьМетодWebdav("PROPPATCH", АдресФайлаHRef, ЗаголовкиHTTP, ПараметрыСинхронизации, XMLЗапрос);
КонецФункции
// Считывает уникальный служебный реквизит файла на сервере webdav.
Функция ПолучитьUID1C(АдресФайлаHRef, ПараметрыСинхронизации)
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
ЗаголовкиHTTP["Content-type"] = "text/xml";
ЗаголовкиHTTP["Accept"] = "text/xml";
ЗаголовкиHTTP["Depth"] = "0";
Результат = ВыполнитьМетодWebdav("PROPFIND",АдресФайлаHRef,ЗаголовкиHTTP,ПараметрыСинхронизации,
"<?xml version=""1.0"" encoding=""utf-8""?>
|<D:propfind xmlns:D=""DAV:"" xmlns:U=""tsov.pro""><D:prop>
|<U:UID1C />
|</D:prop></D:propfind>");
Если Результат.Успешно Тогда
КонтекстXml = ОпределитьКонтекстXML(ПараметрыСинхронизации.Ответ.ПолучитьТелоКакСтроку());
НайденныеEtag = ВычислитьXPath("//*[local-name()='propstat'][contains(./*[local-name()='status'],'200 OK')]/*[local-name()='prop']/*[local-name()='UID1C']",КонтекстXml).ПолучитьСледующий();
Если НайденныеEtag <> Неопределено Тогда
Возврат НайденныеEtag.ТекстовоеСодержимое;
КонецЕсли;
Иначе
ЗаписатьВЖурналСобытийСинхронизацииФайлов(Результат.ТекстОшибки, ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
КонецЕсли;
Возврат "";
КонецФункции
// Проверяет, поддерживает ли сервер webdav пользовательские свойства для файла.
Функция ПроверитьВозможностьUID1C(АдресФайлаHRef, UID1C, ПараметрыСинхронизации)
ОбновитьUID1CФайла(АдресФайлаHRef, UID1C, ПараметрыСинхронизации);
Возврат ЗначениеЗаполнено(ПолучитьUID1C(АдресФайлаHRef, ПараметрыСинхронизации));
КонецФункции
// Выполняет MCKOL на сервере webdav.
Функция ВызватьМетодMKCOL(АдресФайлаHRef, ПараметрыСинхронизации)
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
Возврат ВыполнитьМетодWebdav("MKCOL", АдресФайлаHRef, ЗаголовкиHTTP, ПараметрыСинхронизации);
КонецФункции
// Выполняет DELETE на сервере webdav.
Функция ВызватьМетодDELETE(АдресФайлаHRef, ПараметрыСинхронизации)
HrefБезСлеша = ЗакончитьБезСлеша(АдресФайлаHRef);
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
Возврат ВыполнитьМетодWebdav("DELETE", HrefБезСлеша, ЗаголовкиHTTP, ПараметрыСинхронизации);
КонецФункции
// Получает Etag файла на сервере.
Функция ПолучитьEtag(АдресФайлаHRef, ПараметрыСинхронизации)
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
ЗаголовкиHTTP["Content-type"] = "text/xml";
ЗаголовкиHTTP["Accept"] = "text/xml";
ЗаголовкиHTTP["Depth"] = "0";
Результат = ВыполнитьМетодWebdav("PROPFIND",АдресФайлаHRef,ЗаголовкиHTTP,ПараметрыСинхронизации,
"<?xml version=""1.0"" encoding=""utf-8""?>
|<D:propfind xmlns:D=""DAV:""><D:prop>
|<D:getetag />
|</D:prop></D:propfind>");
Если Результат.Успешно Тогда
КонтекстXml = ОпределитьКонтекстXML(ПараметрыСинхронизации.Ответ.ПолучитьТелоКакСтроку());
НайденныеEtag = ВычислитьXPath("//*[local-name()='propstat'][contains(./*[local-name()='status'],'200 OK')]/*[local-name()='prop']/*[local-name()='getetag']",КонтекстXml).ПолучитьСледующий();
Если НайденныеEtag <> Неопределено Тогда
Возврат НайденныеEtag.ТекстовоеСодержимое;
КонецЕсли;
Иначе
ЗаписатьВЖурналСобытийСинхронизацииФайлов(Результат.ТекстОшибки, ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
КонецЕсли;
Возврат "";
КонецФункции
// Инициализирует объект HTTPСоединение.
Функция СоздатьHTTPСоединениеWebdav(СтруктураHref, ПараметрыСинхронизации, Таймаут)
ИнтернетПрокси = Неопределено;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ПолучениеФайловИзИнтернета") Тогда
МодульПолучениеФайловИзИнтернета = ОбщегоНазначения.ОбщийМодуль("ПолучениеФайловИзИнтернета");
ИнтернетПрокси = МодульПолучениеФайловИзИнтернета.ПолучитьПрокси("https");
КонецЕсли;
ЗащищенноеСоединение = Неопределено;
Если СтруктураHref.Схема = "https" Тогда
ЗащищенноеСоединение = ОбщегоНазначенияКлиентСервер.НовоеЗащищенноеСоединение();
КонецЕсли;
Если Не ЗначениеЗаполнено(СтруктураHref.Порт) Тогда
Результат = Новый HTTPСоединение(
СтруктураHref.Хост,
,
ПараметрыСинхронизации.Логин,
ПараметрыСинхронизации.Пароль,
ИнтернетПрокси,
Таймаут,
ЗащищенноеСоединение);
Иначе
Результат = Новый HTTPСоединение(
СтруктураHref.Хост,
СтруктураHref.Порт,
ПараметрыСинхронизации.Логин,
ПараметрыСинхронизации.Пароль,
ИнтернетПрокси,
Таймаут,
ЗащищенноеСоединение);
КонецЕсли;
Возврат Результат;
КонецФункции
// Вызывает метод GET на сервере webdav и возвращает адрес загруженного файла во временном хранилище.
Функция ВызватьМетодGET(АдресФайлаHRef, ИдентификаторEtag, ПараметрыСинхронизации, ДатаМодификацииФайла = Неопределено, ДлинаФайла = Неопределено)
Результат = Новый Структура("Успешно, АдресВременныхДанных, ТекстОшибки");
СтруктураHref = СтруктураURIРаскодированная(АдресФайлаHRef);
Таймаут = ?(ДлинаФайла <> Неопределено, РассчитатьТаймаут(ДлинаФайла), 43200);
Соединение = СоздатьHTTPСоединениеWebdav(СтруктураHref, ПараметрыСинхронизации, Таймаут);
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
ЗаголовкиHTTP["Accept"] = "application/octet-stream";
HTTPЗапросWebdav = Новый HTTPЗапрос(СтруктураHref.ПутьНаСервере, ЗаголовкиHTTP);
ПараметрыСинхронизации.Ответ = Соединение.Получить(HTTPЗапросWebdav);
Результат = ПроверитьИсключениеHTTP1С(ПараметрыСинхронизации.Ответ, АдресФайлаHRef);
Если НЕ Результат.Успешно Тогда
Возврат Результат;
КонецЕсли;
ФайлСДвоичнымиДанными = ПараметрыСинхронизации.Ответ.ПолучитьТелоКакДвоичныеДанные(); // ДвоичныеДанные
ИдентификаторEtag = ?(ПараметрыСинхронизации.Ответ.Заголовки["ИдентификаторEtag"] = Неопределено, "", ПараметрыСинхронизации.Ответ.Заголовки["ИдентификаторEtag"]);
ДатаМодификацииФайла = ?(ПараметрыСинхронизации.Ответ.Заголовки["Last-Modified"] = Неопределено,ТекущаяУниверсальнаяДата(),ДатаRFC1123(ПараметрыСинхронизации.Ответ.Заголовки["Last-Modified"]));
ДлинаФайла = ФайлСДвоичнымиДанными.Размер();
АдресВременныхДанных = ПоместитьВоВременноеХранилище(ФайлСДвоичнымиДанными);
Результат.Вставить("АдресЗагруженногоФайла", АдресВременныхДанных);
Возврат Результат;
КонецФункции
// Помещает файл на сервер webdav с помощью метода PUT и возвращает присвоенный etag в переменную.
Функция ВызватьМетодPUT(АдресФайлаHRef, ФайлСсылка, ПараметрыСинхронизации, ЭтоФайл)
ФайлСДвоичнымиДанными = РаботаСФайлами.ДвоичныеДанныеФайла(ФайлСсылка);
СтруктураHref = СтруктураURIРаскодированная(АдресФайлаHRef);
Таймаут = РассчитатьТаймаут(ФайлСДвоичнымиДанными.Размер());
Соединение = СоздатьHTTPСоединениеWebdav(СтруктураHref, ПараметрыСинхронизации, Таймаут);
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
ЗаголовкиHTTP["Content-Type"] = "application/octet-stream";
HTTPЗапросWebdav = Новый HTTPЗапрос(СтруктураHref.ПутьНаСервере, ЗаголовкиHTTP);
HTTPЗапросWebdav.УстановитьТелоИзДвоичныхДанных(ФайлСДвоичнымиДанными);
ПараметрыСинхронизации.Ответ = Соединение.Записать(HTTPЗапросWebdav);
ПроверитьИсключениеHTTP1С(ПараметрыСинхронизации.Ответ, АдресФайлаHRef);
Возврат ПолучитьEtag(АдресФайлаHRef,ПараметрыСинхронизации);
КонецФункции
// Загружает файл с сервера с созданием новой версии.
Функция ЗагрузитьФайлССервера(ПараметрыФайла, ЭтоФайл = Неопределено)
ИмяФайла = ПараметрыФайла.ИмяФайла;
АдресФайла = ПараметрыФайла.Href;
ИдентификаторEtag = ПараметрыФайла.Etag;
ДатаМодификацииФайла = ПараметрыФайла.ДатаМодификацииФайла;
ДлинаФайла = ПараметрыФайла.ДлинаФайла;
ОбъектВладелец = ПараметрыФайла.ОбъектВладелец;
СсылкаСуществующегоФайла = ПараметрыФайла.СсылкаСуществующегоФайла;
ПараметрыСинхронизации = ПараметрыФайла.ПараметрыСинхронизации;
ТекстСобытия = НСтр("ru = 'Загрузка файла с сервера: %1'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСобытия, ПараметрыФайла.ИмяФайла), ПараметрыСинхронизации.УчетнаяЗапись);
РезультатЗагрузки = ВызватьМетодGET(АдресФайла, ИдентификаторEtag, ПараметрыСинхронизации, ДатаМодификацииФайла, ДлинаФайла);
Если ЭтоФайл = Неопределено Тогда
ЭтоФайл = ЭтоВладелецФайлов(ПараметрыФайла.ОбъектВладелец);
КонецЕсли;
Если РезультатЗагрузки.Успешно И РезультатЗагрузки.АдресЗагруженногоФайла <> Неопределено Тогда
АдресЗагруженногоФайла = РезультатЗагрузки.АдресЗагруженногоФайла;
СтруктураИмениФайла = Новый Файл(ПараметрыФайла.ИмяФайла);
Если СсылкаСуществующегоФайла = Неопределено Тогда
ПараметрыДобавляемогоФайла = РаботаСФайлами.ПараметрыДобавленияФайла();
Если СтрНачинаетсяС(ОбъектВладелец.Метаданные().ПолноеИмя(), "Справочник") И ОбъектВладелец.ЭтоГруппа Тогда
ПараметрыДобавляемогоФайла.ГруппаФайлов = ОбъектВладелец;
ПараметрыДобавляемогоФайла.ВладелецФайлов = ОбъектВладелец.ВладелецФайла;
Иначе
ПараметрыДобавляемогоФайла.ВладелецФайлов = ОбъектВладелец;
КонецЕсли;
ПараметрыДобавляемогоФайла.Автор = ПараметрыСинхронизации.АвторФайлов;
ПараметрыДобавляемогоФайла.ИмяБезРасширения = СтруктураИмениФайла.ИмяБезРасширения;
ПараметрыДобавляемогоФайла.РасширениеБезТочки = ОбщегоНазначенияКлиентСервер.РасширениеБезТочки(СтруктураИмениФайла.Расширение);
ПараметрыДобавляемогоФайла.ВремяИзмененияУниверсальное = ДатаМодификацииФайла;
НовыйФайл = РаботаСФайлами.ДобавитьФайл(ПараметрыДобавляемогоФайла, АдресЗагруженногоФайла);
ЗанятьФайлДляРедактированияСервер(НовыйФайл, ПараметрыСинхронизации.АвторФайлов);
Иначе
Режим = ?(СсылкаСуществующегоФайла.ХранитьВерсии, "ФайлСВерсией", "Файл");
СведенияОФайле = РаботаСФайламиКлиентСервер.СведенияОФайле(Режим);
СведенияОФайле.ИмяБезРасширения = СтруктураИмениФайла.ИмяБезРасширения;
СведенияОФайле.АдресВременногоХранилищаФайла = АдресЗагруженногоФайла;
СведенияОФайле.РасширениеБезТочки = ОбщегоНазначенияКлиентСервер.РасширениеБезТочки(СтруктураИмениФайла.Расширение);
СведенияОФайле.ВремяИзмененияУниверсальное = ДатаМодификацииФайла;
Если СведенияОФайле.ХранитьВерсии Тогда
СведенияОФайле.НоваяВерсияАвтор = ПараметрыСинхронизации.АвторФайлов;
КонецЕсли;
РаботаСФайламиСлужебныйВызовСервера.СохранитьИзмененияФайла(СсылкаСуществующегоФайла, СведенияОФайле, Истина, "", "", Ложь);
НовыйФайл = СсылкаСуществующегоФайла;
КонецЕсли;
ФайлUID1C = Строка(НовыйФайл.Ссылка.УникальныйИдентификатор());
ОбновитьUID1CФайла(АдресФайла, ФайлUID1C, ПараметрыСинхронизации);
ЗапомнитьСерверныеДанныеСсылки(НовыйФайл.Ссылка, АдресФайла, ИдентификаторEtag, ЭтоФайл, ОбъектВладелец, Ложь, ПараметрыСинхронизации.УчетнаяЗапись);
ТекстСообщения = НСтр("ru = 'Загружен файл из облачного сервиса: ""%1""'");
СтатусДляЖурналаРегистрации = УровеньЖурналаРегистрации.Информация;
Иначе
ТекстСообщения = НСтр("ru = 'Не удалось загрузить файл ""%1"" из облачного сервиса по причине:'") + " " + Символы.ПС + РезультатЗагрузки.ТекстОшибки;
СтатусДляЖурналаРегистрации = УровеньЖурналаРегистрации.Ошибка;
КонецЕсли;
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСообщения, ИмяФайла), ПараметрыСинхронизации.УчетнаяЗапись, СтатусДляЖурналаРегистрации);
Возврат НовыйФайл;
КонецФункции
// Записывает событие в журнал регистрации.
Процедура ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстСообщения, УчетнаяЗапись, УстанавливаемыйУровеньЖурналаРегистрации = Неопределено)
Если УстанавливаемыйУровеньЖурналаРегистрации = Неопределено Тогда
УстанавливаемыйУровеньЖурналаРегистрации = УровеньЖурналаРегистрации.Информация;
КонецЕсли;
ЗаписьЖурналаРегистрации(СобытиеЖурналаРегистрацииСинхронизация(),
УстанавливаемыйУровеньЖурналаРегистрации,,
УчетнаяЗапись,
ТекстСообщения);
КонецПроцедуры
Функция СобытиеЖурналаРегистрацииСинхронизация()
Возврат НСтр("ru = 'Синхронизация файлов с облачным сервисом'", ОбщегоНазначения.КодОсновногоЯзыка());
КонецФункции
// Возвращает дату, преобразованную из формата RFC 1123 в тип Дата.
Функция ДатаRFC1123(ДатаСтрокойHTTP)
ИменаМесяцев = "janfebmaraprmayjunjulaugsepoctnovdec";
// rfc1123-date = wkday "," SP date1 SP time SP "GMT".
ПозицияПервогоПробела = СтрНайти(ДатаСтрокойHTTP, " ");//с первого пробела до второго пробела идет дата.
ПодстрокаДата = Сред(ДатаСтрокойHTTP,ПозицияПервогоПробела + 1);
ПодстрокаВремя = Сред(ПодстрокаДата, 13);
ПодстрокаДата = Лев(ПодстрокаДата, 11);
ПозицияПервогоПробела = СтрНайти(ПодстрокаВремя, " ");
ПодстрокаВремя = Лев(ПодстрокаВремя,ПозицияПервогоПробела - 1);
// date1 = 2DIGIT SP month SP 4DIGIT.
ПодстрокаДень = Лев(ПодстрокаДата, 2);
ПодстрокаМесяц = Формат(Цел(СтрНайти(ИменаМесяцев,НРег(Сред(ПодстрокаДата,4,3))) / 3)+1, "ЧЦ=2; ЧН=00; ЧВН=");
ПодстрокаГод = Сред(ПодстрокаДата, 8);
// time = 2DIGIT ":" 2DIGIT ":" 2DIGIT.
ПодстрокаЧас = Лев(ПодстрокаВремя, 2);
ПодстрокаМинута = Сред(ПодстрокаВремя, 4, 2);
ПодстрокаСекунда = Прав(ПодстрокаВремя, 2);
Возврат Дата(ПодстрокаГод + ПодстрокаМесяц + ПодстрокаДень + ПодстрокаЧас + ПодстрокаМинута + ПодстрокаСекунда);
КонецФункции
// Считывает основные данные о состоянии каталога на сервере. Используется для проверки подключения.
Процедура ПрочитатьПараметрыКаталога(РезультатПроверки, HttpАдрес, СтруктураОбмена)
СтруктураАдресаHTTP = СтруктураURIРаскодированная(HttpАдрес);
АдресСервера = КодироватьURIПоСтруктуре(СтруктураАдресаHTTP);
Попытка
// получаем каталог
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
ЗаголовкиHTTP["Content-type"] = "text/xml";
ЗаголовкиHTTP["Accept"] = "text/xml";
ЗаголовкиHTTP["Depth"] = "0";
Результат = ВыполнитьМетодWebdav("PROPFIND", АдресСервера, ЗаголовкиHTTP, СтруктураОбмена,
"<?xml version=""1.0"" encoding=""utf-8""?>
|<D:propfind xmlns:D=""DAV:"" xmlns:U=""tsov.pro""><D:prop>
|<D:quota-used-bytes /><D:quota-available-bytes />
|</D:prop></D:propfind>"
, РезультатПроверки.РезультатПротокол);
Если Результат.Успешно = Ложь Тогда
РезультатСозданияКорневойПапки = ВызватьМетодMKCOL(АдресСервера, СтруктураОбмена);
Если РезультатСозданияКорневойПапки.Успешно = Истина Тогда
Результат = ВыполнитьМетодWebdav("PROPFIND", АдресСервера, ЗаголовкиHTTP, СтруктураОбмена,
"<?xml version=""1.0"" encoding=""utf-8""?>
|<D:propfind xmlns:D=""DAV:"" xmlns:U=""tsov.pro""><D:prop>
|<D:quota-used-bytes /><D:quota-available-bytes />
|</D:prop></D:propfind>"
, РезультатПроверки.РезультатПротокол);
КонецЕсли;
КонецЕсли;
Если Результат.Успешно = Ложь Тогда
РезультатПроверки.Отказ = Истина;
РезультатПроверки.КодОшибки = Результат.КодОшибки;
РезультатПроверки.РезультатТекст = Результат.ТекстОшибки;
ЗаписатьВЖурналСобытийСинхронизацииФайлов(Результат.ТекстОшибки, СтруктураОбмена.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
Возврат;
КонецЕсли;
КонтекстДокументаXML = ОпределитьКонтекстXML(СтруктураОбмена.Ответ.ПолучитьТелоКакСтроку());
РезультатXPath = ВычислитьXPath("//*[local-name()='response']",КонтекстДокументаXML);
НайденныйResponse = РезультатXPath.ПолучитьСледующий();
Пока НайденныйResponse <> Неопределено Цикл
НайденныйPropstat = ВычислитьXPath("./*[local-name()='propstat'][contains(./*[local-name()='status'],'200 OK')]/*[local-name()='prop']", КонтекстДокументаXML, НайденныйResponse).ПолучитьСледующий();
Если НайденныйPropstat<>Неопределено Тогда
Для каждого ДочернийУзелPropstat Из НайденныйPropstat.ДочерниеУзлы Цикл
Если ДочернийУзелPropstat.ЛокальноеИмя = "quota-available-bytes" Тогда
Попытка
РазмерВМегабайтах = Окр(Число(ДочернийУзелPropstat.ТекстовоеСодержимое)/1024/1024, 1);
Исключение
РазмерВМегабайтах = 0;
КонецПопытки;
ИнформацияОСвободномМесте = НСтр("ru = 'Свободное место : %1 Мб'");
РезультатПроверки.РезультатТекст = РезультатПроверки.РезультатТекст + ?(ПустаяСтрока(РезультатПроверки.РезультатТекст), "", Символы.ПС)
+ СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ИнформацияОСвободномМесте, РазмерВМегабайтах);
ИначеЕсли ДочернийУзелPropstat.ЛокальноеИмя = "quota-used-bytes" Тогда
Попытка
РазмерВМегабайтах = Окр(Число(ДочернийУзелPropstat.ТекстовоеСодержимое)/1024/1024, 1);
Исключение
РазмерВМегабайтах = 0;
КонецПопытки;
ИнформацияОЗанятомМесте = НСтр("ru = 'Занято : %1 Мб'");
РезультатПроверки.РезультатТекст = РезультатПроверки.РезультатТекст + ?(ПустаяСтрока(РезультатПроверки.РезультатТекст), "", Символы.ПС)
+ СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ИнформацияОЗанятомМесте, РазмерВМегабайтах);
КонецЕсли;
КонецЦикла;
КонецЕсли;
НайденныйResponse = РезультатXPath.ПолучитьСледующий();
КонецЦикла;
Исключение
ОписаниеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
РезультатПроверки.РезультатТекст = РезультатПроверки.РезультатТекст + ?(ПустаяСтрока(РезультатПроверки.РезультатТекст), "", Символы.ПС) + ОписаниеОшибки;
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ОписаниеОшибки, СтруктураОбмена.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
РезультатПроверки.Отказ = Истина;
КонецПопытки;
КонецПроцедуры
// Возвращает структуру URI
Функция СтруктураURIРаскодированная(Знач СтрокаURI)
СтрокаURI = СокрЛП(СтрокаURI);
// Схема
Схема = "";
Позиция = СтрНайти(СтрокаURI, "://");
Если Позиция > 0 Тогда
Схема = НРег(Лев(СтрокаURI, Позиция - 1));
СтрокаURI = Сред(СтрокаURI, Позиция + 3);
КонецЕсли;
// Строка соединения и путь на сервере.
СтрокаСоединения = СтрокаURI;
ПутьНаСервере = "";
Позиция = СтрНайти(СтрокаСоединения, "/");
Если Позиция > 0 Тогда
// Включая первый слэш
ПутьНаСервере = Сред(СтрокаСоединения, Позиция);
СтрокаСоединения = Лев(СтрокаСоединения, Позиция - 1);
КонецЕсли;
// Информация пользователя и имя сервера.
СтрокаАвторизации = "";
ИмяСервера = СтрокаСоединения;
Позиция = СтрНайти(СтрокаСоединения, "@");
Если Позиция > 0 Тогда
СтрокаАвторизации = Лев(СтрокаСоединения, Позиция - 1);
ИмяСервера = Сред(СтрокаСоединения, Позиция + 1);
КонецЕсли;
// Логин и пароль
Логин = СтрокаАвторизации;
Пароль = "";
Позиция = СтрНайти(СтрокаАвторизации, ":");
Если Позиция > 0 Тогда
Логин = Лев(СтрокаАвторизации, Позиция - 1);
Пароль = Сред(СтрокаАвторизации, Позиция + 1);
КонецЕсли;
// Хост и порт
Хост = ИмяСервера;
Порт = "";
Позиция = СтрНайти(ИмяСервера, ":");
Если Позиция > 0 Тогда
Хост = Лев(ИмяСервера, Позиция - 1);
Порт = Сред(ИмяСервера, Позиция + 1);
КонецЕсли;
Результат = Новый Структура;
Результат.Вставить("Схема", НРег(Схема));
Результат.Вставить("Логин", Логин);
Результат.Вставить("Пароль", Пароль);
Результат.Вставить("ИмяСервера", НРег(ИмяСервера));
Результат.Вставить("Хост", НРег(Хост));
Результат.Вставить("Порт", ?(ПустаяСтрока(Порт), Неопределено, Число(Порт)));
Результат.Вставить("ПутьНаСервере", РаскодироватьСтроку(ЗакончитьБезСлеша(ПутьНаСервере),СпособКодированияСтроки.URLВКодировкеURL));
// Путь на сервере всегда будет с начальным, но без конечного слэша, универсально для файлов и папок.
Возврат Результат;
КонецФункции
// Возвращает URI, составленный из структуры.
Функция КодироватьURIПоСтруктуре(Знач СтруктураURI, ВключаяПутьНаСервере = Истина)
Результат = "";
// Протокол
Если Не ПустаяСтрока(СтруктураURI.Схема) Тогда
Результат = Результат + СтруктураURI.Схема + "://";
КонецЕсли;
// Авторизация
Если Не ПустаяСтрока(СтруктураURI.Логин) Тогда
Результат = Результат + СтруктураURI.Логин + ":" + СтруктураURI.Пароль + "@";
КонецЕсли;
// Все остальное
Результат = Результат + СтруктураURI.Хост;
Если ЗначениеЗаполнено(СтруктураURI.Порт) Тогда
Результат = Результат + ":" + ?(ТипЗнч(СтруктураURI.Порт) = Тип("Число"), Формат(СтруктураURI.Порт, "ЧГ=0"), СтруктураURI.Порт);
КонецЕсли;
Результат = Результат + ?(ВключаяПутьНаСервере, ЗакончитьБезСлеша(СтруктураURI.ПутьНаСервере), "");
// Всегда без конечного слеша
Возврат Результат;
КонецФункции
// Возвращает строку, гарантированно начинающуюся прямым слешем.
Функция НачатьСлешем(Знач ИсходнаяСтрока)
Возврат ?(Лев(ИсходнаяСтрока,1)="/", ИсходнаяСтрока, "/"+ИсходнаяСтрока);
КонецФункции
// Возвращает строку, гарантированно заканчивающуюся без прямого слэша.
Функция ЗакончитьБезСлеша(Знач ИсходнаяСтрока)
Возврат ?(Прав(ИсходнаяСтрока,1)="/", Лев(ИсходнаяСтрока, СтрДлина(ИсходнаяСтрока)-1), ИсходнаяСтрока);
КонецФункции
// Возвращает результат сравнения путей двух URI, вне зависимости от наличия начального и конечного прямого слеша,
// кодирования спецсимволов, а также адреса сервера.
//
Функция ЭтоОдинаковыеПутиURI(URI1, URI2, ЧувствительноКРегистру = Истина)
// Гарантирует идентичность вне зависимости от слэшей и кодирования.
СтруктураURI1 = СтруктураURIРаскодированная(URI1);
СтруктураURI2 = СтруктураURIРаскодированная(URI2);
Если НЕ ЧувствительноКРегистру Тогда
СтруктураURI1.ПутьНаСервере = НРег(СтруктураURI1.ПутьНаСервере);
СтруктураURI2.ПутьНаСервере = НРег(СтруктураURI2.ПутьНаСервере);
КонецЕсли;
Возврат КодироватьURIПоСтруктуре(СтруктураURI1,Истина) = КодироватьURIПоСтруктуре(СтруктураURI2,Истина);
КонецФункции
// Возвращает имя файла по адресу файла.
Функция ИмяФайлаИзАдреса(АдресФайла)
URIСтрока = ЗакончитьБезСлеша(АдресФайла);
ДлинаURI = СтрДлина(URIСтрока);
// Находим последний слэш, после него будет имя файла.
Для Индекс = 1 По ДлинаURI Цикл
СимволURI = Сред(URIСтрока,ДлинаURI - Индекс + 1, 1);
Если СимволURI = "/" Тогда
Возврат РаскодироватьСтроку(Сред(URIСтрока,ДлинаURI - Индекс + 2), СпособКодированияСтроки.КодировкаURL);
КонецЕсли;
КонецЦикла;
Возврат РаскодироватьСтроку(URIСтрока, СпособКодированияСтроки.КодировкаURL);
КонецФункции
// Сохраняет данные о Href и Etag файла или папки в базе данных.
Процедура ЗапомнитьСерверныеДанныеСсылки(
Ссылка,
АдресФайлаHRef,
ИдентификаторEtag,
ЭтоФайл,
ВладелецФайла,
ЭтоПапка,
УчетнаяЗапись = Неопределено)
ЗаписьРегистра = РегистрыСведений.СтатусыСинхронизацииФайловСОблачнымСервисом.СоздатьМенеджерЗаписи();
ЗаписьРегистра.Файл = Ссылка;
ЗаписьРегистра.Href = АдресФайлаHRef;
ЗаписьРегистра.Etag = ИдентификаторEtag;
ЗаписьРегистра.УникальныйИдентификатор1С = ?(ТипЗнч(Ссылка) = Тип("Строка"), "", Ссылка.УникальныйИдентификатор());
ЗаписьРегистра.ЭтоФайл = ЭтоФайл;
ЗаписьРегистра.ЭтоВладелецФайла = ЭтоПапка;
ЗаписьРегистра.ВладелецФайла = ВладелецФайла;
ЗаписьРегистра.УчетнаяЗапись = УчетнаяЗапись;
ЗаписьРегистра.Синхронизирован = Ложь;
ЗаписьРегистра.ДатаСинхронизацииНачало = ТекущаяДатаСеанса();
ЗаписьРегистра.ДатаСинхронизацииЗавершение = ТекущаяДатаСеанса() + 1800; // 30 минут
ЗаписьРегистра.НомерСеанса = НомерСеансаИнформационнойБазы();
ЗаписьРегистра.Записать(Истина);
КонецПроцедуры
// Сохраняет данные о Href и Etag файла или папки в базе данных.
Процедура УстановитьСтатусСинхронизации(СведенияОФайле, УчетнаяЗапись = Неопределено)
ЗаписьРегистра = РегистрыСведений.СтатусыСинхронизацииФайловСОблачнымСервисом.СоздатьМенеджерЗаписи();
ЗаписьРегистра.Файл = СведенияОФайле.ФайлСсылка;
ЗаписьРегистра.Href = СведенияОФайле.ToHref;
ЗаписьРегистра.Etag = СведенияОФайле.ToEtag;
ЗаписьРегистра.УникальныйИдентификатор1С = СведенияОФайле.ФайлСсылка.УникальныйИдентификатор();
ЗаписьРегистра.ЭтоФайл = СведенияОФайле.ЭтоФайл;
ЗаписьРегистра.ЭтоВладелецФайла = СведенияОФайле.ЭтоПапка;
ЗаписьРегистра.ВладелецФайла = СведенияОФайле.Родитель;
ЗаписьРегистра.Синхронизирован = СведенияОФайле.Обработан;
ЗаписьРегистра.ДатаСинхронизацииНачало = ТекущаяДатаСеанса();
ЗаписьРегистра.ДатаСинхронизацииЗавершение = ТекущаяДатаСеанса();
ЗаписьРегистра.НомерСеанса = НомерСеансаИнформационнойБазы();
ЗаписьРегистра.УчетнаяЗапись = УчетнаяЗапись;
ЗаписьРегистра.Записать(Истина);
КонецПроцедуры
// Удаляет данные о Href и Etag файла или папки в базе данных.
Процедура УдалитьСерверныеДанныеСсылки(Ссылка, УчетнаяЗапись)
НаборРегистра = РегистрыСведений.СтатусыСинхронизацииФайловСОблачнымСервисом.СоздатьНаборЗаписей();
НаборРегистра.Отбор.Файл.Установить(Ссылка);
НаборРегистра.Отбор.УчетнаяЗапись.Установить(УчетнаяЗапись);
НаборРегистра.Записать(Истина);
КонецПроцедуры
// Определяет контекст xml
Функция ОпределитьКонтекстXML(ТекстXML)
ЧтениеXMLТекста = Новый ЧтениеXML;
ЧтениеXMLТекста.УстановитьСтроку(ТекстXML);
ПостроительDOMДляXML = Новый ПостроительDOM;
ДокументDOMДляXML = ПостроительDOMДляXML.Прочитать(ЧтениеXMLТекста);
РазыменовательИменДляXML = Новый РазыменовательПространствИменDOM(ДокументDOMДляXML);
Возврат Новый Структура("ДокументDOM,РазыменовательDOM", ДокументDOMДляXML, РазыменовательИменДляXML);
КонецФункции
// Вычисляет выражение xpath для контекста xml.
Функция ВычислитьXPath(Выражение, Контекст, УзелКонтекста = Неопределено)
Возврат Контекст.ДокументDOM.ВычислитьВыражениеXPath(Выражение,?(УзелКонтекста=Неопределено,Контекст.ДокументDOM,УзелКонтекста),Контекст.РазыменовательDOM);
КонецФункции
// Возвращает Href, рассчитанный для строки из таблицы файлов, методом поиска всех родителей.
Функция РассчитатьHref(СтрокаФайлов,ТаблицаФайлов)
// Рекурсивно собираем наименования.
НайденыСтрокиФайлов = ТаблицаФайлов.Найти(СтрокаФайлов.Родитель,"ФайлСсылка");
Если НайденыСтрокиФайлов = Неопределено Тогда
Возврат ?(ЗначениеЗаполнено(СтрокаФайлов.Наименование),
ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла(СтрокаФайлов.Наименование, "-") + "/","");
Иначе
Возврат РассчитатьHref(НайденыСтрокиФайлов,ТаблицаФайлов)
+ ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла(СтрокаФайлов.Наименование, "-") +"/";
КонецЕсли;
КонецФункции
// Возвращает строку таблицы файлов по URI, при этом, учитывается возможное различное написание URI
// (например, закодированное, относительное или абсолютное и т.п.).
//
Функция НайтиСтрокуПоURI(ИскомоеURI, ТаблицаСURI, КолонкаURI)
Для каждого СтрокаТаблицы Из ТаблицаСURI Цикл
Если ЭтоОдинаковыеПутиURI(ИскомоеURI,СтрокаТаблицы[КолонкаURI]) Тогда
Возврат СтрокаТаблицы;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
// Вычисляется уровень строки файлов, рекурсивным алгоритмом.
Функция РекурсивноУровень(СтрокаФайлов,ТаблицаФайлов)
// Равен уровню в базе или на сервере, в зависимости от того, где он меньше.
НайденыСтрокиФайлов = ТаблицаФайлов.НайтиСтроки(Новый Структура("ФайлСсылка", СтрокаФайлов.Родитель));
КоличествоПрибавления = ?(НайденыСтрокиФайлов.Количество() = 0, 0, 1);
Для каждого НайденнаяСтрокаФайлов Из НайденыСтрокиФайлов Цикл
КоличествоПрибавления = КоличествоПрибавления + РекурсивноУровень(НайденнаяСтрокаФайлов,ТаблицаФайлов);
КонецЦикла;
Возврат КоличествоПрибавления;
КонецФункции
// Вычисляется уровень файла на сервере webdav, рекурсивным алгоритмом.
Функция РекурсивноУровеньНаСервере(СтрокаФайлов,ТаблицаФайлов)
НайденыСтрокиФайлов = ТаблицаФайлов.НайтиСтроки(Новый Структура("ФайлСсылка", СтрокаФайлов.РодительСервер));
КоличествоПрибавления = ?(НайденыСтрокиФайлов.Количество() = 0, 0, 1);
Для каждого НайденнаяСтрокаФайлов Из НайденыСтрокиФайлов Цикл
КоличествоПрибавления = КоличествоПрибавления + РекурсивноУровеньНаСервере(НайденнаяСтрокаФайлов, ТаблицаФайлов);
КонецЦикла;
Возврат КоличествоПрибавления;
КонецФункции
// Вычисляет уровни всех строк таблицы файлов.
Процедура ВычислитьУровеньРекурсивно(ТаблицаФайлов)
ТаблицаФайлов.Индексы.Добавить("ФайлСсылка");
Для каждого СтрокаФайлов Из ТаблицаФайлов Цикл
Если НЕ ЗначениеЗаполнено(СтрокаФайлов.ФайлСсылка) Тогда
Продолжить;
КонецЕсли;
// Равен уровню в базе или на сервере, в зависимости от того, где он меньше.
УровеньВБазе = РекурсивноУровень(СтрокаФайлов, ТаблицаФайлов);
УровеньНаСервере = РекурсивноУровеньНаСервере(СтрокаФайлов, ТаблицаФайлов);
Если УровеньНаСервере = 0 Тогда
СтрокаФайлов.Уровень = УровеньВБазе;
СтрокаФайлов.РодительСортировка = СтрокаФайлов.Родитель;
Иначе
Если УровеньВБазе <= УровеньНаСервере Тогда
СтрокаФайлов.Уровень = УровеньВБазе;
СтрокаФайлов.РодительСортировка = СтрокаФайлов.Родитель;
Иначе
СтрокаФайлов.Уровень = УровеньНаСервере;
СтрокаФайлов.РодительСортировка = СтрокаФайлов.РодительСервер;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// При изменении серверного пути к папке необходимо заменить пути к подчиненным файлам, что и делает эта процедура.
Процедура РекурсивноОбновитьСсылкиПодчиненных(СтрокаФайлов,знач ToHref,знач ToHref2,ТаблицаФайлов)
// Меняем корневую ссылку, всегда должна быть закодирована.
СтрокаФайлов.ToHref = СтрЗаменить(
РаскодироватьСтроку(ЗакончитьБезСлеша(СтрокаФайлов.ToHref), СпособКодированияСтроки.URLВКодировкеURL),
РаскодироватьСтроку(ЗакончитьБезСлеша(ToHref), СпособКодированияСтроки.URLВКодировкеURL),
РаскодироватьСтроку(ЗакончитьБезСлеша(ToHref2), СпособКодированияСтроки.URLВКодировкеURL));
НайденныеПодчиненныеСтроки = ТаблицаФайлов.НайтиСтроки(Новый Структура("РодительСервер", СтрокаФайлов.Ссылка));
Для каждого ПодчиненнаяСтрока Из НайденныеПодчиненныеСтроки Цикл
РекурсивноОбновитьСсылкиПодчиненных(ПодчиненнаяСтрока,ToHref,ToHref2,ТаблицаФайлов);
КонецЦикла;
КонецПроцедуры
// Рекурсивно загружает перечень файлов с сервера в таблицу файлов.
Процедура СкачатьДеревоФайловРекурсивно(ТекущиеСтрокиДереваФайлов, HttpАдрес, ПараметрыСинхронизации, Отказ=Ложь)
СтруктураАдресаHTTP = СтруктураURIРаскодированная(HttpАдрес);
АдресОблачногоСервиса = КодироватьURIПоСтруктуре(СтруктураАдресаHTTP, Ложь);
АдресСервера = КодироватьURIПоСтруктуре(СтруктураАдресаHTTP);
Попытка
// Получаем каталог
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
ЗаголовкиHTTP["Content-type"] = "text/xml";
ЗаголовкиHTTP["Accept"] = "text/xml";
ЗаголовкиHTTP["Depth"] = "1";
Результат = ВыполнитьМетодWebdav("PROPFIND", АдресСервера, ЗаголовкиHTTP, ПараметрыСинхронизации,
"<?xml version=""1.0"" encoding=""utf-8""?>
|<D:propfind xmlns:D=""DAV:"" xmlns:U=""tsov.pro""><D:prop>
|<D:getetag /><U:UID1C /><D:resourcetype />
|<D:getlastmodified /><D:getcontentlength />
|</D:prop></D:propfind>");
Если Результат.Успешно = Ложь Тогда
ЗаписатьВЖурналСобытийСинхронизацииФайлов(Результат.ТекстОшибки, ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
Возврат;
КонецЕсли;
КонтекстДокументаXML = ОпределитьКонтекстXML(ПараметрыСинхронизации.Ответ.ПолучитьТелоКакСтроку());
РезультатXPath = ВычислитьXPath("//*[local-name()='response']", КонтекстДокументаXML);
НайденныйResponse = РезультатXPath.ПолучитьСледующий();
Пока НайденныйResponse <> Неопределено Цикл
// Href есть всегда, иначе это критическая ошибка.
НайденныйHref = ВычислитьXPath("./*[local-name()='href']", КонтекстДокументаXML, НайденныйResponse).ПолучитьСледующий();
Если НайденныйHref = Неопределено Тогда
ТекстОшибки = НСтр("ru = 'Ошибка ответа от сервера: не найден HREF в %1'");
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстОшибки, АдресСервера);
КонецЕсли;
ТекстHref = ЗакончитьБезСлеша(НачатьСлешем(НайденныйHref.ТекстовоеСодержимое));
Если ЭтоОдинаковыеПутиURI(АдресОблачногоСервиса + ТекстHref, АдресСервера) Тогда
НайденныйResponse = РезультатXPath.ПолучитьСледующий();
Продолжить;
КонецЕсли;
НоваяСтрокаДереваФайлов = ТекущиеСтрокиДереваФайлов.Добавить();
// Всегда закодирована
НоваяСтрокаДереваФайлов.Href = АдресОблачногоСервиса + ТекстHref;
НоваяСтрокаДереваФайлов.ИмяФайла = ИмяФайлаИзАдреса(НоваяСтрокаДереваФайлов.Href);
НоваяСтрокаДереваФайлов.Etag = "";
НоваяСтрокаДереваФайлов.UID1C = "";
НоваяСтрокаДереваФайлов.ЭтоПапка = Неопределено;
НайденныйPropstat = ВычислитьXPath("./*[local-name()='propstat'][contains(./*[local-name()='status'],'200 OK')]/*[local-name()='prop']", КонтекстДокументаXML, НайденныйResponse).ПолучитьСледующий();
Если НайденныйPropstat <> Неопределено Тогда
Для каждого ДочернийУзелPropstat Из НайденныйPropstat.ДочерниеУзлы Цикл
Если ДочернийУзелPropstat.ЛокальноеИмя = "resourcetype" Тогда
НоваяСтрокаДереваФайлов.ЭтоПапка = ВычислитьXPath("./*[local-name()='collection']", КонтекстДокументаXML, ДочернийУзелPropstat).ПолучитьСледующий() <> Неопределено;
ИначеЕсли ДочернийУзелPropstat.ЛокальноеИмя = "UID1C" Тогда
НоваяСтрокаДереваФайлов.UID1C = ДочернийУзелPropstat.ТекстовоеСодержимое;
ИначеЕсли ДочернийУзелPropstat.ЛокальноеИмя = "getetag" Тогда
НоваяСтрокаДереваФайлов.Etag = ДочернийУзелPropstat.ТекстовоеСодержимое;
ИначеЕсли ДочернийУзелPropstat.ЛокальноеИмя = "getlastmodified" Тогда
НоваяСтрокаДереваФайлов.ДатаМодификации = ДатаRFC1123(ДочернийУзелPropstat.ТекстовоеСодержимое);//UTC
ИначеЕсли ДочернийУзелPropstat.ЛокальноеИмя = "getcontentlength" Тогда
НоваяСтрокаДереваФайлов.Длина = Число(СтрЗаменить(ДочернийУзелPropstat.ТекстовоеСодержимое," ",""));
КонецЕсли;
КонецЦикла;
КонецЕсли;
// Если не было UID, пробуем получить его отдельно, это нужно, например, для owncloud.
Если НЕ ЗначениеЗаполнено(НоваяСтрокаДереваФайлов.UID1C) Тогда
НоваяСтрокаДереваФайлов.UID1C = ПолучитьUID1C(НоваяСтрокаДереваФайлов.Href, ПараметрыСинхронизации);
КонецЕсли;
НайденныйResponse = РезультатXPath.ПолучитьСледующий();
КонецЦикла;
Исключение
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
Отказ = Истина;
КонецПопытки;
Для каждого СтрокаДереваФайлов Из ТекущиеСтрокиДереваФайлов Цикл
Если СтрокаДереваФайлов.ЭтоПапка = Истина Тогда
СкачатьДеревоФайловРекурсивно(СтрокаДереваФайлов.Строки, СтрокаДереваФайлов.Href, ПараметрыСинхронизации, Отказ);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Загружает с сервера webdav новые папки и файлы, которых еще нет в базе, и отражает их в таблице файлов.
Процедура ЗагрузитьНовыеПрисоединенныеФайлы(СтрокиДереваФайлов, ТаблицаФайлов, ПараметрыСинхронизации, ОбъектВладелец = Неопределено)
Для каждого СтрокаДереваФайлов Из СтрокиДереваФайлов Цикл
Если СтрокаДереваФайлов.ЭтоПапка Тогда
// Папка определяется сначала по UID1C, если не найдена, то по старому Href, т.к. UID может теряться при
// редактировании, а новый Href еще не может быть найден в базе,
// если UID потерялся при редактировали и папку переместили в другую папку (Href поменялся), то она будет загружена в
// новую карточку папки поиск по Href оправдан, т.к. он уникален на файловом сервере для каждой папки.
ТекущаяПапкаФайлов = Неопределено;
// Теоретически еще можно искать файлы по Etag, но встанет вопрос дублей, поэтому дальше не ищем.
Если Не ПустаяСтрока(СтрокаДереваФайлов.UID1C) Тогда
ОпределитьТекущуюПапкуФайлов(СтрокаДереваФайлов.UID1C, ТекущаяПапкаФайлов);
КонецЕсли;
Если (ТекущаяПапкаФайлов = Неопределено) И (ТаблицаФайлов.Найти(СтрокаДереваФайлов.Href, "Href") = Неопределено) Тогда
// Это новая папка на сервере.
// Если папка лежит в корне каталога обмена или корне типа синхронизируемого объекта метаданных, она не относится к объекту-владельцу.
// Такие папки игнорируются.
Если ОбъектВладелец = Неопределено
Или ТипЗнч(ОбъектВладелец) = Тип("СправочникСсылка.ИдентификаторыОбъектовМетаданных") Тогда
Продолжить;
КонецЕсли;
// Проверим возможность хранения UID1C, и если нельзя - то папка не грузится.
Если НЕ ПроверитьВозможностьUID1C(СтрокаДереваФайлов.Href, Строка(Новый УникальныйИдентификатор), ПараметрыСинхронизации) Тогда
ТекстСобытия = НСтр("ru = 'Невозможно сохранение дополнительных свойств файла, он не будет загружен: %1'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСобытия, СтрокаДереваФайлов.ИмяФайла), ПараметрыСинхронизации.УчетнаяЗапись);
Продолжить;
КонецЕсли;
Попытка
ТекущаяПапкаФайлов = РаботаСФайламиСлужебныйВызовСервера.СоздатьПапкуФайлов(СтрокаДереваФайлов.ИмяФайла, ОбъектВладелец, ПараметрыСинхронизации.АвторФайлов);
СтрокаДереваФайлов.UID1C = Строка(ТекущаяПапкаФайлов.УникальныйИдентификатор());
ОбновитьUID1CФайла(СтрокаДереваФайлов.Href, СтрокаДереваФайлов.UID1C, ПараметрыСинхронизации);
НоваяСтрокаТаблицыФайлов = ТаблицаФайлов.Добавить();
НоваяСтрокаТаблицыФайлов.ФайлСсылка = ТекущаяПапкаФайлов;
НоваяСтрокаТаблицыФайлов.ПометкаУдаления = Ложь;
НоваяСтрокаТаблицыФайлов.Родитель = ОбъектВладелец;
НоваяСтрокаТаблицыФайлов.ЭтоПапка = Истина;
НоваяСтрокаТаблицыФайлов.UID1C = СтрокаДереваФайлов.UID1C;
НоваяСтрокаТаблицыФайлов.ЕстьВБазе = Истина;
НоваяСтрокаТаблицыФайлов.ЕстьНаСервере = Истина;
НоваяСтрокаТаблицыФайлов.ИзмененНаСервере = Ложь;
НоваяСтрокаТаблицыФайлов.Изменения = ТекущаяПапкаФайлов;
НоваяСтрокаТаблицыФайлов.Href = "";
НоваяСтрокаТаблицыФайлов.Etag = "";
НоваяСтрокаТаблицыФайлов.ToHref = СтрокаДереваФайлов.Href;
НоваяСтрокаТаблицыФайлов.ToEtag = СтрокаДереваФайлов.Etag;
НоваяСтрокаТаблицыФайлов.РодительСервер = ОбъектВладелец;
НоваяСтрокаТаблицыФайлов.Наименование = СтрокаДереваФайлов.ИмяФайла;
НоваяСтрокаТаблицыФайлов.НаименованиеСервер = СтрокаДереваФайлов.ИмяФайла;
НоваяСтрокаТаблицыФайлов.Обработан = Истина;
НоваяСтрокаТаблицыФайлов.ЭтоФайл = Истина;
ЗапомнитьСерверныеДанныеСсылки(
НоваяСтрокаТаблицыФайлов.ФайлСсылка,
НоваяСтрокаТаблицыФайлов.ToHref,
НоваяСтрокаТаблицыФайлов.ToEtag,
НоваяСтрокаТаблицыФайлов.ЭтоФайл,
НоваяСтрокаТаблицыФайлов.Родитель,
НоваяСтрокаТаблицыФайлов.ЭтоПапка,
ПараметрыСинхронизации.УчетнаяЗапись);
ТекстСобытия = НСтр("ru = 'Загружена папка с сервера: %1'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСобытия, НоваяСтрокаТаблицыФайлов.НаименованиеСервер), ПараметрыСинхронизации.УчетнаяЗапись);
Исключение
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()) ,ПараметрыСинхронизации.УчетнаяЗапись);
КонецПопытки;
Иначе
Если Не ЗначениеЗаполнено(ТекущаяПапкаФайлов) Тогда
// В РС СтатусыСинхронизацииФайловСОблачнымСервисом нет данных о папке, ищем ее в файлах.
СтараяСтрокаТаблицыФайлов = ТаблицаФайлов.Найти(СтрокаДереваФайлов.Href, "Href");
Если СтараяСтрокаТаблицыФайлов = Неопределено Тогда
СтараяСтрокаТаблицыФайлов = ТаблицаФайлов.Найти(РаскодироватьСтроку(СтрокаДереваФайлов.Href,
СпособКодированияСтроки.URLВКодировкеURL), "Href");
КонецЕсли;
Если СтараяСтрокаТаблицыФайлов = Неопределено Тогда
ТекстСобытия = НСтр("ru = 'Пропущена синхронизация папки %1. Папка отсутствует на сервере.'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
ТекстСобытия,РаскодироватьСтроку(СтрокаДереваФайлов.Href, СпособКодированияСтроки.URLВКодировкеURL)),
ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
Продолжить;
КонецЕсли;
// Папка найдена по пути Href, теперь по UID1C ищем запись в РС СтатусыСинхронизацииФайловСОблачнымСервисом
ОпределитьТекущуюПапкуФайлов(СтараяСтрокаТаблицыФайлов.UID1C, ТекущаяПапкаФайлов);
Если Не ЗначениеЗаполнено(ТекущаяПапкаФайлов) Тогда
ТекстСобытия = НСтр("ru = 'Невозможно синхронизировать папку %1.
|Идентификатор папки %2 отсутствует в сведениях о синхронизации файлов.'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
ТекстСобытия, РаскодироватьСтроку(СтрокаДереваФайлов.Href, СпособКодированияСтроки.URLВКодировкеURL),
СтараяСтрокаТаблицыФайлов.UID1C),
ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
Продолжить;
КонецЕсли;
Иначе
СтараяСтрокаТаблицыФайлов = ТаблицаФайлов.Найти(ТекущаяПапкаФайлов.Ссылка, "ФайлСсылка");
КонецЕсли;
// Обновим ToHref
Если СтараяСтрокаТаблицыФайлов <> Неопределено Тогда
СтараяСтрокаТаблицыФайлов.ToHref = СтрокаДереваФайлов.Href;
СтараяСтрокаТаблицыФайлов.ToEtag = СтрокаДереваФайлов.Etag;
СтараяСтрокаТаблицыФайлов.РодительСервер = ОбъектВладелец;
СтараяСтрокаТаблицыФайлов.НаименованиеСервер = СтрокаДереваФайлов.ИмяФайла;
СтараяСтрокаТаблицыФайлов.ЕстьНаСервере = Истина;
СтараяСтрокаТаблицыФайлов.ИзмененНаСервере = НЕ ЭтоОдинаковыеПутиURI(СтараяСтрокаТаблицыФайлов.ToHref,СтараяСтрокаТаблицыФайлов.Href);
КонецЕсли;
КонецЕсли;
// Для подчиненных строк это теперь родитель.
ЗагрузитьНовыеПрисоединенныеФайлы(СтрокаДереваФайлов.Строки, ТаблицаФайлов, ПараметрыСинхронизации, ТекущаяПапкаФайлов.Ссылка);
Иначе
// Это файл
// Файл определяется сначала по UID1C, если не найден, то по старому Href, т.к. UID может теряться при
// редактировании, а новый Href еще не может быть найден в базе,
// если UID потерялся при редактировали и файл переместили в другую папку (Href поменялся), то он будет загружен в
// новую карточку файла поиск по Href оправдан, т.к. он уникален на файловом сервере для каждого файла.
// Файл будет пропущен, т.к. был добавлен пользователем в некорректную папку, у которой отсутствует владелец.
Если ОбъектВладелец = Неопределено
Или ТипЗнч(ОбъектВладелец) = Тип("СправочникСсылка.ИдентификаторыОбъектовМетаданных") Тогда
Продолжить;
КонецЕсли;
ТекущийФайл = НайтиСтрокуПоURI(СтрокаДереваФайлов.Href, ТаблицаФайлов, "Href");
Если (ТекущийФайл = Неопределено) ИЛИ (ТаблицаФайлов.Найти(ТекущийФайл.ФайлСсылка ,"ФайлСсылка") = Неопределено) Тогда
// Это новый файл на сервере - грузим его.
Если НЕ ПроверитьВозможностьUID1C(СтрокаДереваФайлов.Href, Строка(Новый УникальныйИдентификатор), ПараметрыСинхронизации) Тогда
ТекстСобытия = НСтр("ru = 'Невозможно сохранение дополнительных свойств файла, он не будет загружен: %1'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСобытия, СтрокаДереваФайлов.ИмяФайла), ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
Продолжить;
КонецЕсли;
Попытка
ПараметрыФайла = Новый Структура;
ПараметрыФайла.Вставить("ИмяФайла", СтрокаДереваФайлов.ИмяФайла);
ПараметрыФайла.Вставить("Href", СтрокаДереваФайлов.Href);
ПараметрыФайла.Вставить("Etag", СтрокаДереваФайлов.Etag);
ПараметрыФайла.Вставить("ДатаМодификацииФайла", СтрокаДереваФайлов.ДатаМодификации);
ПараметрыФайла.Вставить("ДлинаФайла", СтрокаДереваФайлов.Длина);
ПараметрыФайла.Вставить("ДляПользователя", ПараметрыСинхронизации.АвторФайлов);
ПараметрыФайла.Вставить("ОбъектВладелец", ОбъектВладелец);
ПараметрыФайла.Вставить("СсылкаСуществующегоФайла", Неопределено);
ПараметрыФайла.Вставить("ПараметрыСинхронизации", ПараметрыСинхронизации);
СсылкаСуществующегоФайла = ЗагрузитьФайлССервера(ПараметрыФайла);
СтрокаДереваФайлов.UID1C = Строка(СсылкаСуществующегоФайла.Ссылка.УникальныйИдентификатор());
НоваяСтрокаТаблицыФайлов = ТаблицаФайлов.Добавить();
НоваяСтрокаТаблицыФайлов.ФайлСсылка = СсылкаСуществующегоФайла;
НоваяСтрокаТаблицыФайлов.ПометкаУдаления = Ложь;
НоваяСтрокаТаблицыФайлов.Родитель = ОбъектВладелец;
НоваяСтрокаТаблицыФайлов.ЭтоПапка = Ложь;
НоваяСтрокаТаблицыФайлов.UID1C = СтрокаДереваФайлов.UID1C;
НоваяСтрокаТаблицыФайлов.ЕстьВБазе = Ложь;
НоваяСтрокаТаблицыФайлов.ЕстьНаСервере = Истина;
НоваяСтрокаТаблицыФайлов.ИзмененНаСервере = Ложь;
НоваяСтрокаТаблицыФайлов.Href = "";
НоваяСтрокаТаблицыФайлов.Etag = "";
НоваяСтрокаТаблицыФайлов.ToHref = СтрокаДереваФайлов.Href;
НоваяСтрокаТаблицыФайлов.ToEtag = СтрокаДереваФайлов.Etag;
НоваяСтрокаТаблицыФайлов.РодительСервер = ОбъектВладелец;
НоваяСтрокаТаблицыФайлов.Наименование = СтрокаДереваФайлов.ИмяФайла;
НоваяСтрокаТаблицыФайлов.НаименованиеСервер = СтрокаДереваФайлов.ИмяФайла;
НоваяСтрокаТаблицыФайлов.Обработан = Истина;
НоваяСтрокаТаблицыФайлов.ЭтоФайл = Истина;
Исключение
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
КонецПопытки;
Иначе
// Обновим ToHref
СтараяСтрокаТаблицыФайлов = ТаблицаФайлов.Найти(ТекущийФайл.ФайлСсылка,"ФайлСсылка");
СтараяСтрокаТаблицыФайлов.ToHref = СтрокаДереваФайлов.Href;
СтараяСтрокаТаблицыФайлов.ToEtag = СтрокаДереваФайлов.Etag;
СтараяСтрокаТаблицыФайлов.РодительСервер = ОбъектВладелец;
СтараяСтрокаТаблицыФайлов.НаименованиеСервер = СтрокаДереваФайлов.ИмяФайла;
СтараяСтрокаТаблицыФайлов.ЕстьНаСервере = Истина;
СтараяСтрокаТаблицыФайлов.ИзмененНаСервере = НЕ ЭтоОдинаковыеПутиURI(СтараяСтрокаТаблицыФайлов.ToHref, СтараяСтрокаТаблицыФайлов.Href);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ОпределитьТекущуюПапкуФайлов(Знач UID1C, ТекущаяПапкаФайлов)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| СтатусыСинхронизацииФайловСОблачнымСервисом.Файл КАК Ссылка
|ИЗ
| РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
|ГДЕ
| СтатусыСинхронизацииФайловСОблачнымСервисом.УникальныйИдентификатор1С = &УникальныйИдентификатор1С";
Запрос.УстановитьПараметр("УникальныйИдентификатор1С", Новый УникальныйИдентификатор(UID1C));
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ТекущаяПапкаФайлов = ВыборкаДетальныеЗаписи;
КонецЦикла;
КонецПроцедуры
Процедура ЗаполнитьДанныеИзОблачногоСервиса(СтрокиДереваФайлов, ТаблицаФайлов, ПараметрыСинхронизации, ОбъектВладелец = Неопределено)
Для каждого СтрокаДереваФайлов Из СтрокиДереваФайлов Цикл
Если СтрокаДереваФайлов.ЭтоПапка = Истина Тогда //папки
// Папка определяется сначала по UID1C, если не найдена, то по старому Href, т.к. UID может теряться при
// редактировании, а новый Href еще не может быть найден в базе,
// если UID потерялся при редактировали и папку переместили в другую папку (Href поменялся), то она будет загружена в
// новую карточку папки поиск по Href оправдан, т.к. он уникален на файловом сервере для каждой папки.
ТекущаяПапкаФайлов = Неопределено;
// Теоретически еще можно искать файлы по Etag, но встанет вопрос дублей, поэтому дальше не ищем.
Если Не ПустаяСтрока(СтрокаДереваФайлов.UID1C) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СтатусыСинхронизацииФайловСОблачнымСервисом.Файл
|ИЗ
| РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
|ГДЕ
| СтатусыСинхронизацииФайловСОблачнымСервисом.УникальныйИдентификатор1С = &УникальныйИдентификатор1С";
Запрос.УстановитьПараметр("УникальныйИдентификатор1С", Новый УникальныйИдентификатор(СтрокаДереваФайлов.UID1C));
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ТекущаяПапкаФайлов = ВыборкаДетальныеЗаписи.Файл; // ОпределяемыйТип.ПрисоединенныйФайл
КонецЦикла;
КонецЕсли;
Если ТекущаяПапкаФайлов = Неопределено Тогда
ТекущаяПапкаФайлов = НайтиСтрокуПоURI(СтрокаДереваФайлов.Href, ТаблицаФайлов, "Href");// может быть помечена на удаление, тогда у нее нет Href, и тут она не будет найдена.
КонецЕсли;
Если ТекущаяПапкаФайлов = Неопределено ИЛИ ТаблицаФайлов.Найти(ТекущаяПапкаФайлов.Ссылка, "ФайлСсылка") = Неопределено Тогда
Продолжить;
КонецЕсли;
Если (ТекущаяПапкаФайлов <> Неопределено) ИЛИ (ТаблицаФайлов.Найти(ТекущаяПапкаФайлов.Ссылка,"ФайлСсылка") <> Неопределено) Тогда
СтараяСтрокаТаблицыФайлов = ТаблицаФайлов.Найти(ТекущаяПапкаФайлов.Ссылка, "ФайлСсылка");
СтараяСтрокаТаблицыФайлов.ToHref = СтрокаДереваФайлов.Href;
СтараяСтрокаТаблицыФайлов.ToEtag = СтрокаДереваФайлов.Etag;
СтараяСтрокаТаблицыФайлов.РодительСервер = ОбъектВладелец;
СтараяСтрокаТаблицыФайлов.НаименованиеСервер = СтрокаДереваФайлов.ИмяФайла;
СтараяСтрокаТаблицыФайлов.ЕстьНаСервере = Истина;
СтараяСтрокаТаблицыФайлов.ИзмененНаСервере = НЕ ЭтоОдинаковыеПутиURI(СтараяСтрокаТаблицыФайлов.ToHref,СтараяСтрокаТаблицыФайлов.Href);
КонецЕсли;
// Для подчиненных строк это теперь родитель.
ЗаполнитьДанныеИзОблачногоСервиса(СтрокаДереваФайлов.Строки, ТаблицаФайлов, ПараметрыСинхронизации, ТекущаяПапкаФайлов.Ссылка);
Иначе
// Это файл
// Файл определяется сначала по UID1C, если не найден, то по старому Href, т.к. UID может теряться при
// редактировании, а новый Href еще не может быть найден в базе,
// если UID потерялся при редактировали и файл переместили в другую папку (Href поменялся), то он будет загружен в
// новую карточку файла поиск по Href оправдан, т.к. он уникален на файловом сервере для каждого файла.
ТекущийФайл = НайтиСтрокуПоURI(СтрокаДереваФайлов.Href, ТаблицаФайлов, "Href");
Если (ТекущийФайл <> Неопределено) И (ТаблицаФайлов.Найти(ТекущийФайл.ФайлСсылка,"ФайлСсылка") <> Неопределено) Тогда
// Обновим ToHref
СтараяСтрокаТаблицыФайлов = ТаблицаФайлов.Найти(ТекущийФайл.ФайлСсылка,"ФайлСсылка");
СтараяСтрокаТаблицыФайлов.ToHref = СтрокаДереваФайлов.Href;
СтараяСтрокаТаблицыФайлов.ToEtag = СтрокаДереваФайлов.Etag;
СтараяСтрокаТаблицыФайлов.РодительСервер = ОбъектВладелец;
СтараяСтрокаТаблицыФайлов.НаименованиеСервер = СтрокаДереваФайлов.ИмяФайла;
СтараяСтрокаТаблицыФайлов.ЕстьНаСервере = Истина;
СтараяСтрокаТаблицыФайлов.ИзмененНаСервере = НЕ ЭтоОдинаковыеПутиURI(СтараяСтрокаТаблицыФайлов.ToHref,СтараяСтрокаТаблицыФайлов.Href);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Подготавливает структуру обмена, содержащую значения на время сеанса обмена.
Функция ОсновныеОбъектыСинхронизации(УчетнаяЗапись)
СтруктураВозврата = Новый Структура("СтруктураАдресаСервера, Ответ, Логин, Пароль");
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| УчетныеЗаписиСинхронизацииФайлов.Ссылка КАК УчетнаяЗапись,
| УчетныеЗаписиСинхронизацииФайлов.Сервис КАК АдресСервера,
| УчетныеЗаписиСинхронизацииФайлов.КорневаяПапка КАК КорневаяПапка,
| УчетныеЗаписиСинхронизацииФайлов.АвторФайлов КАК АвторФайлов
|ИЗ
| Справочник.УчетныеЗаписиСинхронизацииФайлов КАК УчетныеЗаписиСинхронизацииФайлов
|ГДЕ
| УчетныеЗаписиСинхронизацииФайлов.Ссылка = &Ссылка
| И УчетныеЗаписиСинхронизацииФайлов.ПометкаУдаления = ЛОЖЬ";
Запрос.УстановитьПараметр("Ссылка", УчетнаяЗапись);
Результат = Запрос.Выполнить().Выгрузить();
Если Результат.Количество() = 0 Тогда
Возврат Неопределено;
КонецЕсли;
Для каждого КолонкаРезультата Из Результат.Колонки Цикл
СтруктураВозврата.Вставить(КолонкаРезультата.Имя,Результат[0][КолонкаРезультата.Имя]);
КонецЦикла;
Если Не ПустаяСтрока(СтруктураВозврата.КорневаяПапка) Тогда
СтруктураВозврата.АдресСервера = СтруктураВозврата.АдресСервера + "/" + СтруктураВозврата.КорневаяПапка;
КонецЕсли;
Если ПустаяСтрока(СтруктураВозврата.АвторФайлов) Тогда
СтруктураВозврата.АвторФайлов = УчетнаяЗапись;
КонецЕсли;
СтруктураВозврата.СтруктураАдресаСервера = СтруктураURIРаскодированная(СтруктураВозврата.АдресСервера);
УстановитьПривилегированныйРежим(Истина);
СтруктураВозврата.Логин = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(УчетнаяЗапись, "Логин");
СтруктураВозврата.Пароль = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(УчетнаяЗапись);
УстановитьПривилегированныйРежим(Ложь);
Возврат СтруктураВозврата;
КонецФункции
Процедура СинхронизироватьФайлыСОблачнымСервисом(УчетнаяЗапись)
ПараметрыСинхронизации = ОсновныеОбъектыСинхронизации(УчетнаяЗапись);
Если ПараметрыСинхронизации = Неопределено Тогда
Возврат;
КонецЕсли;
ТекстСобытия = НСтр("ru = 'Начало синхронизации файлов с облачным сервисом.'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстСобытия, ПараметрыСинхронизации.УчетнаяЗапись);
ВыполнитьСинхронизациюФайловОблачнымСервисом(ПараметрыСинхронизации);
ТекстСобытия = НСтр("ru = 'Завершена синхронизация файлов с облачным сервисом'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстСобытия, ПараметрыСинхронизации.УчетнаяЗапись);
КонецПроцедуры
Процедура ВыполнитьСинхронизациюФайловОблачнымСервисом(ПараметрыСинхронизации)
ДеревоФайловСервера = СформироватьСтруктуруДереваФайловСервера();
АдресСервера = КодироватьURIПоСтруктуре(ПараметрыСинхронизации.СтруктураАдресаСервера);
Если Не ПустаяСтрока(ПараметрыСинхронизации.КорневаяПапка) Тогда
ЗаголовкиHTTP = Новый Соответствие;
ЗаголовкиHTTP["User-Agent"] = "1C Enterprise 8.3";
ЗаголовкиHTTP["Content-type"] = "text/xml";
ЗаголовкиHTTP["Accept"] = "text/xml";
ЗаголовкиHTTP["Depth"] = "0";
Результат = ВыполнитьМетодWebdav("PROPFIND", АдресСервера, ЗаголовкиHTTP, ПараметрыСинхронизации);
Если Не Результат.Успешно Тогда
ВызватьМетодMKCOL(АдресСервера, ПараметрыСинхронизации);
КонецЕсли;
КонецЕсли;
Отказ = Ложь;
СинхронизацияВыполнена = Истина;
// Корневая запись о начале синхронизации
ЗапомнитьСерверныеДанныеСсылки("", "", "", Ложь, Неопределено, Ложь, ПараметрыСинхронизации.УчетнаяЗапись);
СкачатьДеревоФайловРекурсивно(ДеревоФайловСервера.Строки, АдресСервера, ПараметрыСинхронизации, Отказ);
Если Отказ = Истина Тогда
ТекстСобытия = НСтр("ru = 'Не удалось загрузить структуру файлов с сервера, синхронизация не выполнена.'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстСобытия, ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
Возврат;
КонецЕсли;
// Сравниваем с деревом файлов в системе, синхронизация идет по уникальному идентификатору.
ТаблицаФайлов = ВыбратьДанныеПоПравилам(ПараметрыСинхронизации.УчетнаяЗапись);
Если ТаблицаФайлов = Неопределено Тогда
ТекстСобытия = НСтр("ru = 'Не удалось получить таблицу файлов из информационной базы, синхронизация не выполнена.'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстСобытия, ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
Возврат;
КонецЕсли;
Для каждого СтрокаТаблицы Из ТаблицаФайлов Цикл
СтрокаТаблицы.UID1C = Строка(СтрокаТаблицы.ФайлСсылка.УникальныйИдентификатор());
КонецЦикла;
// Перебираем дерево, загружаем и добавляем те, которых нет в базе, в таблицу, а по старым заполняем реквизиты с сервера.
ЗагрузитьНовыеПрисоединенныеФайлы(ДеревоФайловСервера.Строки, ТаблицаФайлов, ПараметрыСинхронизации);
ВычислитьУровеньРекурсивно(ТаблицаФайлов);
ТаблицаФайлов.Индексы.Добавить("ФайлСсылка");
ТаблицаФайлов.Сортировать("Уровень, РодительСортировка, ЭтоПапка УБЫВ");
Если Не СинхронизироватьФайлы(ТаблицаФайлов, ПараметрыСинхронизации, АдресСервера) Тогда
СинхронизацияВыполнена = Ложь;
КонецЕсли;
ТаблицаФайлов.Сортировать("Уровень УБЫВ, РодительСортировка, ЭтоПапка УБЫВ");
Если Не СинхронизироватьФайлы(ТаблицаФайлов, ПараметрыСинхронизации, АдресСервера, Истина) Тогда
СинхронизацияВыполнена = Ложь;
КонецЕсли;
ЗаписатьРезультатСинхронизации(ПараметрыСинхронизации.УчетнаяЗапись, СинхронизацияВыполнена);
КонецПроцедуры
Функция СинхронизироватьФайлы(ТаблицаФайлов, ПараметрыСинхронизации, АдресСервера, ЭтоУдалениеФайлов = Ложь)
СинхронизацияВыполнена = Истина;
Для Каждого СтрокаТаблицы Из ТаблицаФайлов Цикл
Если СтрокаТаблицы.Обработан Тогда
УстановитьСтатусСинхронизации(СтрокаТаблицы, ПараметрыСинхронизации.УчетнаяЗапись);
Продолжить;
КонецЕсли;
ОбновитьСтатусСинхронизацииФайла = Ложь;
СозданНовыйВБазе = (НЕ ЗначениеЗаполнено(СтрокаТаблицы.Href)) И (НЕ ЗначениеЗаполнено(СтрокаТаблицы.ToHref));
ИзмененВБазе = ЗначениеЗаполнено(СтрокаТаблицы.Изменения);// что-то поменялось
ИзмененоСодержимоеНаСервере = ЗначениеЗаполнено(СтрокаТаблицы.ToEtag) И (СтрокаТаблицы.Etag <> СтрокаТаблицы.ToEtag);// поменялось содержимое
ИзмененНаСервере = ИзмененоСодержимоеНаСервере ИЛИ СтрокаТаблицы.ИзмененНаСервере;// поменялось имя/подчиненность или содержание
УдаленВБазе = СтрокаТаблицы.ПометкаУдаления;
УдаленНаСервере = ЗначениеЗаполнено(СтрокаТаблицы.Href) И НЕ ЗначениеЗаполнено(СтрокаТаблицы.ToHref);
НачатьТранзакцию();
Попытка
Если ЭтоУдалениеФайлов Тогда
Если УдаленНаСервере И НЕ УдаленВБазе Тогда
ОбновитьСтатусСинхронизацииФайла = УдалитьФайлВОблачномСервисе(ПараметрыСинхронизации, СтрокаТаблицы);
КонецЕсли;
Иначе
Если СозданНовыйВБазе И НЕ УдаленВБазе Тогда
// Загрузить файл на облачный сервер
ОбновитьСтатусСинхронизацииФайла = СоздатьФайлВОблачномСервисе(АдресСервера, ПараметрыСинхронизации, СтрокаТаблицы, ТаблицаФайлов);
ИначеЕсли (ИзмененВБазе ИЛИ ИзмененНаСервере) И НЕ (УдаленВБазе ИЛИ УдаленНаСервере) Тогда
Если ИзмененНаСервере И НЕ ИзмененВБазе Тогда
ОбновитьСтатусСинхронизацииФайла = ИзменитьФайлВОблачномСервисе(ИзмененоСодержимоеНаСервере, ОбновитьСтатусСинхронизацииФайла, ПараметрыСинхронизации, СтрокаТаблицы);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если ОбновитьСтатусСинхронизацииФайла Тогда
// Записываем обновления в регистр сведений статусов.
Если СтрокаТаблицы.ПометкаУдаления Тогда
// Удаляем последний Href, чтобы повторно не идентифицировать.
УдалитьСерверныеДанныеСсылки(СтрокаТаблицы.ФайлСсылка, ПараметрыСинхронизации.УчетнаяЗапись);
Иначе
УстановитьСтатусСинхронизации(СтрокаТаблицы, ПараметрыСинхронизации.УчетнаяЗапись);
КонецЕсли;
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
СтрокаТаблицы.ДатаСинхронизации = ТекущаяДатаСеанса();
УстановитьСтатусСинхронизации(СтрокаТаблицы, ПараметрыСинхронизации.УчетнаяЗапись);
СинхронизацияВыполнена = Ложь;
ТекстОшибки = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Не удалось синхронизировать файл ""%1"" по причине:'"), Строка(СтрокаТаблицы.ФайлСсылка))
+ Символы.ПС + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстОшибки, ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
КонецПопытки;
КонецЦикла;
Возврат СинхронизацияВыполнена;
КонецФункции
Процедура ЗаписатьРезультатСинхронизации(УчетнаяЗапись, Знач СинхронизацияВыполнена)
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить("РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом");
ЭлементБлокировкиДанных.УстановитьЗначение("Файл", "");
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить("РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом");
ЭлементБлокировкиДанных.УстановитьЗначение("УчетнаяЗапись", УчетнаяЗапись);
НачатьТранзакцию();
Попытка
БлокировкаДанных.Заблокировать();
НаборЗаписей = РегистрыСведений.СтатусыСинхронизацииФайловСОблачнымСервисом.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Файл.Установить("", Истина);
НаборЗаписей.Отбор.УчетнаяЗапись.Установить(УчетнаяЗапись, Истина);
НаборЗаписей.Прочитать();
Если НаборЗаписей.Количество() > 0 Тогда
Запись = НаборЗаписей.Получить(0);
Запись.ДатаСинхронизацииЗавершение = ТекущаяДатаСеанса();
Запись.Синхронизирован = СинхронизацияВыполнена;
НаборЗаписей.Записать();
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Функция СформироватьСтруктуруДереваФайловСервера()
ДеревоФайловСервера = Новый ДеревоЗначений;
ДеревоФайловСервера.Колонки.Добавить("Href");
ДеревоФайловСервера.Колонки.Добавить("UID1C");
ДеревоФайловСервера.Колонки.Добавить("Etag");
ДеревоФайловСервера.Колонки.Добавить("ИмяФайла");
ДеревоФайловСервера.Колонки.Добавить("ЭтоПапка");
ДеревоФайловСервера.Колонки.Добавить("ДатаМодификации");
ДеревоФайловСервера.Колонки.Добавить("Длина");
Возврат ДеревоФайловСервера;
КонецФункции
Функция ИзменитьФайлВОблачномСервисе(Знач ИзмененоСодержимоеНаСервере, ОбновитьСтатусСинхронизацииФайла, Знач ПараметрыСинхронизации, Знач СтрокаТаблицы)
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить(СтрокаТаблицы.ФайлСсылка.Метаданные().ПолноеИмя());
ЭлементБлокировки.УстановитьЗначение("Ссылка", СтрокаТаблицы.ФайлСсылка);
НачатьТранзакцию();
Попытка
Блокировка.Заблокировать();
// загрузим с сервера
Если СтрокаТаблицы.ЭтоПапка Тогда
// Возможно можно отследить переименование.
ОбъектСтрокиТаблицы = СтрокаТаблицы.ФайлСсылка.ПолучитьОбъект();
ОбъектСтрокиТаблицы.Наименование = СтрокаТаблицы.НаименованиеСервер;
ОбъектСтрокиТаблицы.Родитель = Неопределено;
ОбъектСтрокиТаблицы.ПометкаУдаления = Ложь;
ОбъектСтрокиТаблицы.Записать();
СтрокаТаблицы.Наименование = СтрокаТаблицы.НаименованиеСервер;
СтрокаТаблицы.Изменения = СтрокаТаблицы.ФайлСсылка;
СтрокаТаблицы.Родитель = СтрокаТаблицы.РодительСервер;
СтрокаТаблицы.ПометкаУдаления = Ложь;
Иначе
СтруктураИмениФайла = Новый Файл(СтрокаТаблицы.НаименованиеСервер);
НовоеРасширениеФайла = ОбщегоНазначенияКлиентСервер.РасширениеБезТочки(СтруктураИмениФайла.Расширение);
// Загружаем только если поменялось содержимое, т.е. Etag, иначе обновляем реквизиты.
Если ИзмененоСодержимоеНаСервере ИЛИ (НовоеРасширениеФайла <> СтрокаТаблицы.ФайлСсылка.Расширение) Тогда
ПараметрыФайла = Новый Структура;
ПараметрыФайла.Вставить("ИмяФайла", СтрокаТаблицы.НаименованиеСервер);
ПараметрыФайла.Вставить("Href", СтрокаТаблицы.ToHref);
ПараметрыФайла.Вставить("Etag", СтрокаТаблицы.ToEtag);
ПараметрыФайла.Вставить("ДатаМодификацииФайла", Неопределено);
ПараметрыФайла.Вставить("ДлинаФайла", Неопределено);
ПараметрыФайла.Вставить("ДляПользователя", ПараметрыСинхронизации.АвторФайлов);
ПараметрыФайла.Вставить("ОбъектВладелец", СтрокаТаблицы.Родитель);
ПараметрыФайла.Вставить("СсылкаСуществующегоФайла", СтрокаТаблицы.ФайлСсылка);
ПараметрыФайла.Вставить("ПараметрыСинхронизации", ПараметрыСинхронизации);
ЗагрузитьФайлССервера(ПараметрыФайла, СтрокаТаблицы.ЭтоФайл);
КонецЕсли;
ОбъектСтрокиТаблицы = СтрокаТаблицы.ФайлСсылка.ПолучитьОбъект();
ОбъектСтрокиТаблицы.Наименование = СтруктураИмениФайла.ИмяБезРасширения;
ОбъектСтрокиТаблицы.ПометкаУдаления = Ложь;
ОбъектСтрокиТаблицы.Записать();
СтрокаТаблицы.Наименование = СтрокаТаблицы.НаименованиеСервер;
СтрокаТаблицы.Изменения = СтрокаТаблицы.ФайлСсылка;
СтрокаТаблицы.Родитель = СтрокаТаблицы.РодительСервер;
СтрокаТаблицы.ПометкаУдаления = Ложь;
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
СтрокаТаблицы.Обработан = Истина;
СтрокаТаблицы.ДатаСинхронизации = ТекущаяДатаСеанса();
ТекстСобытия = НСтр("ru = 'Файл изменен: %1'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСобытия, СтрокаТаблицы.Наименование),
ПараметрыСинхронизации.УчетнаяЗапись);
Возврат Истина;
КонецФункции
Функция УдалитьФайлВОблачномСервисе(Знач ПараметрыСинхронизации, Знач СтрокаТаблицы)
Перем ТекстСобытия;
Если Не ЗначениеЗаполнено(СтрокаТаблицы.ФайлСсылка) Тогда
Возврат Ложь;
КонецЕсли;
Если Не ЭтоСсылкаНаФайл(СтрокаТаблицы.ФайлСсылка) Тогда
СтрокаТаблицы.Обработан = Истина;
Возврат Ложь;
КонецЕсли;
НачатьТранзакцию();
Попытка
ОсвободитьФайл(СтрокаТаблицы.ФайлСсылка);
СтрокаТаблицы.ФайлСсылка.ПолучитьОбъект().УстановитьПометкуУдаления(Истина, Ложь);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ТекстСобытия = НСтр("ru = 'Не удален файл: %1'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСобытия, СтрокаТаблицы.Наименование),
ПараметрыСинхронизации.УчетнаяЗапись);
Возврат Ложь;
КонецПопытки;
СтрокаТаблицы.ПометкаУдаления = Истина;
СтрокаТаблицы.Изменения = СтрокаТаблицы.ФайлСсылка;
СтрокаТаблицы.Обработан = Истина;
СтрокаТаблицы.ДатаСинхронизации = ТекущаяДатаСеанса();
ТекстСобытия = НСтр("ru = 'Удален файл: %1'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСобытия, СтрокаТаблицы.Наименование),
ПараметрыСинхронизации.УчетнаяЗапись);
Возврат Истина;
КонецФункции
Функция ЭтоФайл(Файл)
Возврат Не ЭтоПапкаФайлов(Файл);
КонецФункции
Функция ЭтоСсылкаНаФайл(ОбъектВладелец)
МассивТиповФайлов = Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип.Типы();
Возврат МассивТиповФайлов.Найти(ТипЗнч(ОбъектВладелец)) <> Неопределено;
КонецФункции
Функция РассчитатьТаймаут(Размер)
Таймаут = Цел(Размер / 8192); // размер в мегабайтах * 128
Если Таймаут < 10 Тогда
Возврат 10;
ИначеЕсли Таймаут > 43200 Тогда
Возврат 43200;
КонецЕсли;
Возврат Таймаут;
КонецФункции
Функция СоздатьФайлВОблачномСервисе(Знач АдресСервера, Знач ПараметрыСинхронизации, Знач СтрокаТаблицы, Знач ТаблицаФайлов)
// отправим новый на сервер
СтрокаТаблицы.Наименование = ОбщегоНазначенияКлиентСервер.ЗаменитьНедопустимыеСимволыВИмениФайла(СтрокаТаблицы.Наименование, "-");
СтрокаТаблицы.ToHref = ЗакончитьБезСлеша(АдресСервера) + НачатьСлешем(ЗакончитьБезСлеша(РассчитатьHref(СтрокаТаблицы,ТаблицаФайлов)));
Если ОбщегоНазначения.ОбъектЯвляетсяГруппой(СтрокаТаблицы.ФайлСсылка) Тогда
ВызватьМетодMKCOL(СтрокаТаблицы.ToHref, ПараметрыСинхронизации);
ИначеЕсли СтрокаТаблицы.ЭтоПапка Тогда
ВызватьМетодMKCOL(СтрокаТаблицы.ToHref, ПараметрыСинхронизации);
Иначе
СтрокаТаблицы.ToEtag = ВызватьМетодPUT(СтрокаТаблицы.ToHref, СтрокаТаблицы.ФайлСсылка, ПараметрыСинхронизации, СтрокаТаблицы.ЭтоФайл);
КонецЕсли;
ОбновитьUID1CФайла(СтрокаТаблицы.ToHref, СтрокаТаблицы.UID1C, ПараметрыСинхронизации);
СтрокаТаблицы.РодительСервер = СтрокаТаблицы.Родитель;
СтрокаТаблицы.НаименованиеСервер = СтрокаТаблицы.Наименование;
СтрокаТаблицы.ЕстьНаСервере = Истина;
СтрокаТаблицы.Обработан = Истина;
СтрокаТаблицы.ДатаСинхронизации = ТекущаяДатаСеанса();
ОбъектЯвляетсяГруппой = ОбщегоНазначения.ОбъектЯвляетсяГруппой(СтрокаТаблицы.ФайлСсылка);
Если Не СтрокаТаблицы.ЭтоФайл
И Не СтрокаТаблицы.ЭтоПапка
И Не ОбъектЯвляетсяГруппой Тогда
Если ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СтрокаТаблицы.ФайлСсылка, "Редактирует") <> ПараметрыСинхронизации.АвторФайлов Тогда
ЗанятьФайлДляРедактированияСервер(СтрокаТаблицы.ФайлСсылка, ПараметрыСинхронизации.АвторФайлов);
КонецЕсли;
ИначеЕсли Не СтрокаТаблицы.ЭтоПапка И Не ОбъектЯвляетсяГруппой Тогда
ДанныеФайла = РаботаСФайламиСлужебныйВызовСервера.ДанныеФайла(СтрокаТаблицы.ФайлСсылка);
РаботаСФайламиСлужебныйВызовСервера.ЗанятьФайл(ДанныеФайла, , , ПараметрыСинхронизации.АвторФайлов);
КонецЕсли;
ТекстСобытия = НСтр("ru = 'Создан объект в облачном сервисе %1'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСобытия, СтрокаТаблицы.Наименование), ПараметрыСинхронизации.УчетнаяЗапись);
Возврат Истина;
КонецФункции
Функция ВыбратьДанныеПоПравилам(УчетнаяЗапись, Синхронизировать = ИСТИНА)
ЗапросНастройкиСинхронизации = Новый Запрос;
ЗапросНастройкиСинхронизации.Текст =
"ВЫБРАТЬ
| НастройкиСинхронизацииФайлов.ВладелецФайла КАК ВладелецФайла,
| НастройкиСинхронизацииФайлов.ТипВладельцаФайла КАК ТипВладельцаФайла,
| ИдентификаторыОбъектовМетаданных.Ссылка КАК ИдентификаторВладельца,
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(ИдентификаторыОбъектовМетаданных.Ссылка) <> ТИПЗНАЧЕНИЯ(НастройкиСинхронизацииФайлов.ВладелецФайла)
| ТОГДА ИСТИНА
| ИНАЧЕ ЛОЖЬ
| КОНЕЦ КАК ЭтоНастройкаДляЭлементаСправочника,
| НастройкиСинхронизацииФайлов.ПравилоОтбора КАК ПравилоОтбора,
| НастройкиСинхронизацииФайлов.ЭтоФайл КАК ЭтоФайл,
| НастройкиСинхронизацииФайлов.УчетнаяЗапись КАК УчетнаяЗапись,
| НастройкиСинхронизацииФайлов.Синхронизировать КАК Синхронизировать
|ИЗ
| РегистрСведений.НастройкиСинхронизацииФайлов КАК НастройкиСинхронизацииФайлов
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ИдентификаторыОбъектовМетаданных КАК ИдентификаторыОбъектовМетаданных
| ПО (ТИПЗНАЧЕНИЯ(НастройкиСинхронизацииФайлов.ВладелецФайла) = ТИПЗНАЧЕНИЯ(ИдентификаторыОбъектовМетаданных.ЗначениеПустойСсылки))
|ГДЕ
| НастройкиСинхронизацииФайлов.УчетнаяЗапись = &УчетнаяЗапись";
ЗапросНастройкиСинхронизации.УстановитьПараметр("УчетнаяЗапись", УчетнаяЗапись);
НастройкиСинхронизации = ЗапросНастройкиСинхронизации.Выполнить().Выгрузить();
ТаблицаФайлов = Неопределено;
Для Каждого Настройка Из НастройкиСинхронизации Цикл
СправочникФайлов = ОбщегоНазначения.ОбъектМетаданныхПоИдентификатору(Настройка.ТипВладельцаФайла, Ложь);
Если ТипЗнч(СправочникФайлов) <> Тип("ОбъектМетаданных") Тогда
Продолжить;
КонецЕсли;
Если НЕ ОбщегоНазначения.ОбъектМетаданныхДоступенПоФункциональнымОпциям(СправочникФайлов) Тогда
Продолжить;
КонецЕсли;
ДеревоФайлов = ВыбратьДанныеПоПравилуСинхронизации(Настройка);
Если ДеревоФайлов = Неопределено Тогда
Продолжить;
КонецЕсли;
Если ТаблицаФайлов = Неопределено Тогда
ТаблицаФайлов = Новый ТаблицаЗначений;
Для Каждого Колонка Из ДеревоФайлов.Колонки Цикл
ТаблицаФайлов.Колонки.Добавить(Колонка.Имя);
КонецЦикла;
ТаблицаФайлов.Колонки.Добавить("Синхронизировать", Новый ОписаниеТипов("Число"));
КонецЕсли;
Если Настройка.ЭтоНастройкаДляЭлементаСправочника Тогда
КорневаяПапка = Настройка.ИдентификаторВладельца;
Иначе
КорневаяПапка = Настройка.ВладелецФайла;
КонецЕсли;
Для Каждого СтрокаФайлов Из ДеревоФайлов.Строки Цикл
НоваяСтрока = ТаблицаФайлов.Добавить();
НоваяСтрока.Синхронизировать = ?(Настройка.Синхронизировать, 1, 0);
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаФайлов);
Если НоваяСтрока.ФайлСсылка = Неопределено Тогда
НоваяСтрока.ФайлСсылка = КорневаяПапка;
КонецЕсли;
Если ЗначениеЗаполнено(СтрокаФайлов.ФайлСсылка) Тогда
МетаданныеФайла = СтрокаФайлов.ФайлСсылка.Метаданные();
Если Метаданные.Справочники.Содержит(МетаданныеФайла)
И МетаданныеФайла.Иерархический Тогда
РодительФайла = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СтрокаФайлов.ФайлСсылка, "Родитель");
Если ЗначениеЗаполнено(РодительФайла) Тогда
НоваяСтрока.Родитель = РодительФайла;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Не ЗначениеЗаполнено(НоваяСтрока.Родитель) Тогда
НоваяСтрока.Родитель = КорневаяПапка;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Если ТаблицаФайлов = Неопределено Тогда
Возврат ТаблицаФайлов;
КонецЕсли;
ИменаКолонок = Новый Массив;
Для Каждого Колонка Из ТаблицаФайлов.Колонки Цикл
Если Колонка.Имя <> "Синхронизировать" Тогда
ИменаКолонок.Добавить(Колонка.Имя);
КонецЕсли;
КонецЦикла;
КолонкиГруппировки = СтрСоединить(ИменаКолонок, ",");
ТаблицаФайлов.Свернуть(КолонкиГруппировки, "Синхронизировать");
ТаблицаФайлов.Сортировать("Синхронизировать" + ?(Не Синхронизировать, " Убыв", ""));
УдаляемыеСтроки = Новый Массив;
НесинхронизируемыеВладельцы = Новый Массив;
Для Каждого Строка Из ТаблицаФайлов Цикл
Если (Синхронизировать
И Строка.Синхронизировать > 0)
Или (Не Синхронизировать
И Строка.Синхронизировать = 0) Тогда
Прервать;
КонецЕсли;
УдаляемыеСтроки.Добавить(Строка);
Если Не Синхронизировать
И НесинхронизируемыеВладельцы.Найти(Строка.Родитель) = Неопределено Тогда
НесинхронизируемыеВладельцы.Добавить(Строка.Родитель);
КонецЕсли;
КонецЦикла;
Для Каждого Строка Из УдаляемыеСтроки Цикл
ТаблицаФайлов.Удалить(Строка);
КонецЦикла;
ТаблицаВладельцев = ТаблицаФайлов.Скопировать(, "Родитель");
ТаблицаВладельцев.Свернуть("Родитель");
Если Синхронизировать Тогда
ОбъектыДляСинхронизации = ТаблицаВладельцев.ВыгрузитьКолонку("Родитель");
Иначе
ОбъектыДляСинхронизации = Новый Массив;
Для Каждого СтрокаВладельца Из ТаблицаВладельцев Цикл
Если НесинхронизируемыеВладельцы.Найти(СтрокаВладельца.Родитель) = Неопределено Тогда
ОбъектыДляСинхронизации.Добавить(СтрокаВладельца.Родитель);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(НастройкиСинхронизацииФайлов.ВладелецФайла) = ТИП(Справочник.ИдентификаторыОбъектовМетаданных)
| ТОГДА НастройкиСинхронизацииФайлов.ВладелецФайла
| ИНАЧЕ ИдентификаторыОбъектовМетаданных.Ссылка
| КОНЕЦ КАК ФайлСсылка,
| НастройкиСинхронизацииФайлов.ЭтоФайл КАК ЭтоФайл,
| НастройкиСинхронизацииФайлов.УчетнаяЗапись КАК УчетнаяЗапись,
| НастройкиСинхронизацииФайлов.ВладелецФайла КАК ВладелецФайла,
| НастройкиСинхронизацииФайлов.ТипВладельцаФайла КАК ТипВладельцаФайла
|ПОМЕСТИТЬ ВТВиртуальныеКорневыеПапки
|ИЗ
| РегистрСведений.НастройкиСинхронизацииФайлов КАК НастройкиСинхронизацииФайлов
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ИдентификаторыОбъектовМетаданных КАК ИдентификаторыОбъектовМетаданных
| ПО (ТИПЗНАЧЕНИЯ(НастройкиСинхронизацииФайлов.ВладелецФайла) = ТИПЗНАЧЕНИЯ(ИдентификаторыОбъектовМетаданных.ЗначениеПустойСсылки))
|ГДЕ
| НастройкиСинхронизацииФайлов.Синхронизировать = &Синхронизировать
| И НастройкиСинхронизацииФайлов.УчетнаяЗапись = &УчетнаяЗапись
|
|ИНДЕКСИРОВАТЬ ПО
| УчетнаяЗапись
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТВиртуальныеКорневыеПапки.ФайлСсылка КАК ФайлСсылка,
| ВТВиртуальныеКорневыеПапки.ЭтоФайл КАК ЭтоФайл,
| ЛОЖЬ КАК ПометкаУдаления,
| ИСТИНА КАК ЭтоПапка,
| ИСТИНА КАК ЕстьВБазе,
| ЛОЖЬ КАК ЕстьНаСервере,
| ЛОЖЬ КАК Обработан,
| ЛОЖЬ КАК ИзмененНаСервере,
| СтатусыСинхронизацииФайловСОблачнымСервисом.Href КАК Href,
| СтатусыСинхронизацииФайловСОблачнымСервисом.Etag КАК Etag,
| СтатусыСинхронизацииФайловСОблачнымСервисом.УникальныйИдентификатор1С КАК УникальныйИдентификатор1С,
| ВТВиртуальныеКорневыеПапки.ВладелецФайла КАК ВладелецФайла,
| ВТВиртуальныеКорневыеПапки.ТипВладельцаФайла КАК ТипВладельцаФайла
|ИЗ
| ВТВиртуальныеКорневыеПапки КАК ВТВиртуальныеКорневыеПапки
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
| ПО ВТВиртуальныеКорневыеПапки.УчетнаяЗапись = СтатусыСинхронизацииФайловСОблачнымСервисом.УчетнаяЗапись
| И ВТВиртуальныеКорневыеПапки.ФайлСсылка = СтатусыСинхронизацииФайловСОблачнымСервисом.Файл
|ГДЕ
| ВТВиртуальныеКорневыеПапки.ФайлСсылка В (&ВладельцыФайлов)
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ВТВиртуальныеКорневыеПапки";
Запрос.УстановитьПараметр("УчетнаяЗапись", УчетнаяЗапись);
Запрос.УстановитьПараметр("Синхронизировать", Синхронизировать);
Запрос.УстановитьПараметр("ВладельцыФайлов", ОбъектыДляСинхронизации);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
МассивВиртуальныхПапок = Новый Массив;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Если МассивВиртуальныхПапок.Найти(ВыборкаДетальныеЗаписи.ФайлСсылка) <> Неопределено Тогда
Продолжить;
КонецЕсли;
МассивВиртуальныхПапок.Добавить(ВыборкаДетальныеЗаписи.ФайлСсылка);
СтрокаВиртуальнойКорневойПапки = ТаблицаФайлов.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаВиртуальнойКорневойПапки, ВыборкаДетальныеЗаписи);
СтрокаВиртуальнойКорневойПапки.Наименование = СтрЗаменить(ВыборкаДетальныеЗаписи.ФайлСсылка.Синоним, ":", "");
КонецЦикла;
Возврат ТаблицаФайлов;
КонецФункции
Функция ВыбратьДанныеПоПравилуСинхронизации(НастройкаСинхронизации)
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
НастройкиКомпоновщика = НастройкаСинхронизации.ПравилоОтбора.Получить();
Если НастройкиКомпоновщика <> Неопределено Тогда
КомпоновщикНастроек.ЗагрузитьНастройки(НастройкаСинхронизации.ПравилоОтбора.Получить());
КонецЕсли;
СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
ИсточникДанных = СхемаКомпоновкиДанных.ИсточникиДанных.Добавить();
ИсточникДанных.Имя = "ИсточникДанных1";
ИсточникДанных.ТипИсточникаДанных = "Local";
НаборДанных = СхемаКомпоновкиДанных.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанных.Имя = "НаборДанных1";
НаборДанных.ИсточникДанных = ИсточникДанных.Имя;
СхемаКомпоновкиДанных.ПоляИтога.Очистить();
Если НастройкаСинхронизации.ЭтоНастройкаДляЭлементаСправочника Тогда
ВладелецФайла = НастройкаСинхронизации.ИдентификаторВладельца;
ЭлементИсключение = НастройкаСинхронизации.ВладелецФайла;
Иначе
ВладелецФайла = НастройкаСинхронизации.ВладелецФайла;
ЭлементИсключение = Неопределено;
КонецЕсли;
МассивИсключений = Новый Массив;
ТекстЗапроса = ТекстЗапросаДляСинхронизацииФайлов(ВладелецФайла, НастройкаСинхронизации, МассивИсключений,
ЭлементИсключение);
Если ПустаяСтрока(ТекстЗапроса) Тогда
Возврат Неопределено;
КонецЕсли;
СхемаКомпоновкиДанных.НаборыДанных[0].Запрос = ТекстЗапроса;
Структура = КомпоновщикНастроек.Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ФайлСсылка");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Наименование");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ПометкаУдаления");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Родитель");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ЭтоПапка");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ЕстьВБазе");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ЕстьНаСервере");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Изменения");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Href");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Etag");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Обработан");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ДатаСинхронизации");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("UID1C");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ToHref");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ToEtag");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("РодительСервер");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("НаименованиеСервер");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ИзмененНаСервере");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("Уровень");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("РодительСортировка");
ВыбранноеПоле = Структура.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("ЭтоФайл");
КомпоновщикНастроек.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));
Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("УчетнаяЗапись");
Параметр.Значение = НастройкаСинхронизации.УчетнаяЗапись;
Параметр.Использование = Истина;
Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ТипВладельца");
Параметр.Значение = ТипЗнч(ВладелецФайла.ЗначениеПустойСсылки);
Параметр.Использование = Истина;
Если МассивИсключений.Количество() > 0 Тогда
Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("МассивИсключений");
Параметр.Значение = МассивИсключений;
Параметр.Использование = Истина;
КонецЕсли;
Если НастройкаСинхронизации.ЭтоНастройкаДляЭлементаСправочника Тогда
Параметр = КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ЭлементИсключение");
Параметр.Значение = ЭлементИсключение;
Параметр.Использование = Истина;
КонецЕсли;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ДеревоЗначений = Новый ДеревоЗначений;
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, КомпоновщикНастроек.Настройки,
, , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных);
ПроцессорВывода.УстановитьОбъект(ДеревоЗначений);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
Возврат ДеревоЗначений;
КонецФункции
// Параметры:
// УчетнаяЗапись - СправочникСсылка.УчетныеЗаписиСинхронизацииФайлов
//
Процедура ВыполнитьПроверкуПодключения(УчетнаяЗапись, РезультатПроверки) Экспорт
РезультатПроверки = Новый Структура("РезультатТекст, РезультатПротокол, Отказ, КодОшибки","","",Ложь);
ПараметрыСинхронизации = ОсновныеОбъектыСинхронизации(УчетнаяЗапись);
АдресСервера = КодироватьURIПоСтруктуре(ПараметрыСинхронизации.СтруктураАдресаСервера);
ТекстСобытия = НСтр("ru = 'Начата проверка синхронизации файлов'") + " " + УчетнаяЗапись.Наименование;
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстСобытия, ПараметрыСинхронизации.УчетнаяЗапись);
ПрочитатьПараметрыКаталога(РезультатПроверки,АдресСервера, ПараметрыСинхронизации);
ТекстСобытия = НСтр("ru = 'Завершена проверка синхронизации файлов'") + " " + УчетнаяЗапись.Наименование;
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстСобытия, ПараметрыСинхронизации.УчетнаяЗапись);
КонецПроцедуры
Процедура ОсвободитьЗахваченныеФайлыФон(ПараметрыВызова, АдресВХранилище) Экспорт
УдалитьНесинхронизируемыеФайлы();
КонецПроцедуры
Процедура УдалитьНесинхронизируемыеФайлы()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| УчетныеЗаписиСинхронизацииФайлов.Ссылка КАК УчетнаяЗапись
|ИЗ
| Справочник.УчетныеЗаписиСинхронизацииФайлов КАК УчетныеЗаписиСинхронизацииФайлов
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НастройкиСинхронизацииФайлов КАК НастройкиСинхронизацииФайлов
| ПО (НастройкиСинхронизацииФайлов.УчетнаяЗапись = УчетныеЗаписиСинхронизацииФайлов.Ссылка)
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
| ПО (СтатусыСинхронизацииФайловСОблачнымСервисом.УчетнаяЗапись = УчетныеЗаписиСинхронизацииФайлов.Ссылка)
|ГДЕ
| (УчетныеЗаписиСинхронизацииФайлов.ПометкаУдаления
| ИЛИ НастройкиСинхронизацииФайлов.Синхронизировать <> ИСТИНА)
| И СтатусыСинхронизацииФайловСОблачнымСервисом.УчетнаяЗапись ЕСТЬ НЕ NULL
|
|СГРУППИРОВАТЬ ПО
| УчетныеЗаписиСинхронизацииФайлов.Ссылка";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаУчетнаяЗапись = РезультатЗапроса.Выбрать();
Пока ВыборкаУчетнаяЗапись.Следующий() Цикл
УдалитьНесинхронизируемыеФайлыУчетнойЗаписи(ВыборкаУчетнаяЗапись.УчетнаяЗапись);
КонецЦикла;
КонецПроцедуры
// Освобождение файлов, захваченных учетными записями с пометкой на удаление или с отключенными настройками синхронизации.
//
Процедура УдалитьНесинхронизируемыеФайлыУчетнойЗаписи(УчетнаяЗапись = Неопределено)
ПараметрыСинхронизации = ОсновныеОбъектыСинхронизации(УчетнаяЗапись);
Если ПараметрыСинхронизации = Неопределено Тогда
Возврат;
КонецЕсли;
АдресСервера = КодироватьURIПоСтруктуре(ПараметрыСинхронизации.СтруктураАдресаСервера);
ТекстСобытия = НСтр("ru = 'Начало освобождения файлов, захваченных облачным сервисом.'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстСобытия, ПараметрыСинхронизации.УчетнаяЗапись);
Попытка
ДеревоФайловСервера = Новый ДеревоЗначений;
ДеревоФайловСервера.Колонки.Добавить("Href");
ДеревоФайловСервера.Колонки.Добавить("UID1C");
ДеревоФайловСервера.Колонки.Добавить("Etag");
ДеревоФайловСервера.Колонки.Добавить("ИмяФайла");
ДеревоФайловСервера.Колонки.Добавить("ЭтоПапка");
ДеревоФайловСервера.Колонки.Добавить("ДатаМодификации");
ДеревоФайловСервера.Колонки.Добавить("Длина");
Отказ = Ложь;
СкачатьДеревоФайловРекурсивно(ДеревоФайловСервера.Строки, АдресСервера, ПараметрыСинхронизации, Отказ);
Если Отказ = Истина Тогда
ТекстОшибки = НСтр("ru = 'При загрузке структуры файлов с сервера произошла ошибка, синхронизация не выполнена.'");
ВызватьИсключение ТекстОшибки;
КонецЕсли;
// Сравниваем с деревом файлов в системе, синхронизация идет по уникальному идентификатору.
ТаблицаФайлов = ВыбратьДанныеПоПравилам(УчетнаяЗапись, Ложь);
Если ТаблицаФайлов <> Неопределено Тогда
ВычислитьУровеньРекурсивно(ТаблицаФайлов);
ТаблицаФайлов.Сортировать("ЭтоПапка ВОЗР, Уровень УБЫВ, РодительСортировка УБЫВ");
// Перебираем таблицу и решаем что делать с файлами и папками.
Для Каждого СтрокаТаблицы Из ТаблицаФайлов Цикл
Если СтрокаТаблицы.Обработан Тогда
Продолжить;
КонецЕсли;
НачатьТранзакцию();
Попытка
Если ЗначениеЗаполнено(СтрокаТаблицы.Href) Тогда
// удаляем на сервере
ВызватьМетодDELETE(СтрокаТаблицы.Href, ПараметрыСинхронизации);
ТекстСобытия = НСтр("ru = 'Удален объект в облачном сервисе %1'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ТекстСобытия, СтрокаТаблицы.НаименованиеСервер), ПараметрыСинхронизации.УчетнаяЗапись);
КонецЕсли;
СтрокаТаблицы.РодительСервер = Неопределено;
СтрокаТаблицы.НаименованиеСервер = "";
СтрокаТаблицы.ЕстьНаСервере = Ложь;
СтрокаТаблицы.Обработан = Истина;
Если Не СтрокаТаблицы.ЭтоПапка Тогда
ОсвободитьФайл(СтрокаТаблицы.ФайлСсылка);
КонецЕсли;
// Удаляем последний Href, чтобы повторно не идентифицировать.
УдалитьСерверныеДанныеСсылки(СтрокаТаблицы.ФайлСсылка, УчетнаяЗапись);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
КонецПопытки;
КонецЦикла;
КонецЕсли;
Исключение
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), ПараметрыСинхронизации.УчетнаяЗапись, УровеньЖурналаРегистрации.Ошибка);
КонецПопытки;
ТекстСобытия = НСтр("ru = 'Завершено освобождения файлов, захваченных облачным сервисом'");
ЗаписатьВЖурналСобытийСинхронизацииФайлов(ТекстСобытия, ПараметрыСинхронизации.УчетнаяЗапись);
КонецПроцедуры
Функция ДанныеОтбораЖурналаРегистрации(УчетнаяЗапись) Экспорт
Отбор = Новый Структура;
Отбор.Вставить("СобытиеЖурналаРегистрации ", СобытиеЖурналаРегистрацииСинхронизация());
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| СтатусыСинхронизацииФайловСОблачнымСервисом.НомерСеанса КАК НомерСеанса,
| СтатусыСинхронизацииФайловСОблачнымСервисом.ДатаСинхронизацииНачало КАК ДатаСинхронизацииНачало,
| СтатусыСинхронизацииФайловСОблачнымСервисом.ДатаСинхронизацииЗавершение КАК ДатаСинхронизацииЗавершение
|ИЗ
| РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
|ГДЕ
| СтатусыСинхронизацииФайловСОблачнымСервисом.Файл = """"
| И СтатусыСинхронизацииФайловСОблачнымСервисом.УчетнаяЗапись = &УчетнаяЗапись";
Запрос.УстановитьПараметр("УчетнаяЗапись", УчетнаяЗапись);
РезультатЗапроса = Запрос.Выполнить().Выбрать();
Если РезультатЗапроса.Следующий() Тогда
СписокСеансов = Новый СписокЗначений;
СписокСеансов.Добавить(РезультатЗапроса.НомерСеанса);
Отбор.Вставить("Данные ", УчетнаяЗапись);
Отбор.Вставить("ДатаНачала", РезультатЗапроса.ДатаСинхронизацииНачало);
Отбор.Вставить("ДатаОкончания", РезультатЗапроса.ДатаСинхронизацииЗавершение);
Отбор.Вставить("Сеанс", СписокСеансов);
КонецЕсли;
Возврат Отбор;
КонецФункции
Функция СведенияОСинхронизации(ВладелецФайла = Неопределено) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
| СтатусыСинхронизацииФайловСОблачнымСервисом.УчетнаяЗапись КАК УчетнаяЗапись,
| СтатусыСинхронизацииФайловСОблачнымСервисом.ДатаСинхронизацииНачало КАК ДатаСинхронизации,
| СтатусыСинхронизацииФайловСОблачнымСервисом.НомерСеанса КАК НомерСеанса,
| СтатусыСинхронизацииФайловСОблачнымСервисом.Синхронизирован КАК Синхронизирован,
| СтатусыСинхронизацииФайловСОблачнымСервисом.ДатаСинхронизацииЗавершение КАК ДатаСинхронизацииЗавершение,
| СтатусыСинхронизацииФайловСОблачнымСервисом.Href КАК Href,
| СтатусыСинхронизацииФайловСОблачнымСервисом.УчетнаяЗапись.Наименование КАК УчетнаяЗаписьНаименование,
| СтатусыСинхронизацииФайловСОблачнымСервисом.УчетнаяЗапись.Сервис КАК Сервис
|ИЗ
| РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисом
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СтатусыСинхронизацииФайловСОблачнымСервисом КАК СтатусыСинхронизацииФайловСОблачнымСервисомКорень
| ПО СтатусыСинхронизацииФайловСОблачнымСервисом.УчетнаяЗапись = СтатусыСинхронизацииФайловСОблачнымСервисомКорень.УчетнаяЗапись
| И (СтатусыСинхронизацииФайловСОблачнымСервисомКорень.Файл = """""""")
|ГДЕ
| СтатусыСинхронизацииФайловСОблачнымСервисом.Файл = &Файл";
Запрос.УстановитьПараметр("Файл", ВладелецФайла);
Таблица = Запрос.Выполнить().Выгрузить();
Пока Таблица.Количество() > 0 Цикл
Результат = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(Таблица[0]);
Возврат Результат;
КонецЦикла;
Возврат Новый Структура();
КонецФункции
// Возвращает признак принадлежности узла к плану обмена РИБ.
//
// Параметры:
// УзелИнформационнойБазы - ПланОбменаСсылка - узел плана обмена, для которого требуется получить значение функции.
//
// Возвращаемое значение:
// Булево - Истина - узел принадлежит плану обмена РИБ, иначе Ложь.
//
Функция ЭтоУзелРаспределеннойИнформационнойБазы(Знач УзелИнформационнойБазы)
Возврат РаботаСФайламиСлужебныйПовтИсп.ЭтоУзелРаспределеннойИнформационнойБазы(
УзелИнформационнойБазы.Метаданные().ПолноеИмя());
КонецФункции
#КонецОбласти
#Область ИзвлечениеТекста
Функция ТекстЗапросаДляФайловСНеизвлеченнымТекстом(ИмяСправочника, ЧислоФайловВВыборке,
ПолучитьВсеФайлы, ДополнительныеПоля)
Если ДополнительныеПоля Тогда
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Файлы.Ссылка КАК Ссылка,
| ЕСТЬNULL(РегистрСведенийКодировкиФайлов.Кодировка, """") КАК Кодировка,
| Файлы.Расширение КАК Расширение,
| Файлы.Наименование КАК Наименование
|ИЗ
| &ИмяСправочника КАК Файлы
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КодировкиФайлов КАК РегистрСведенийКодировкиФайлов
| ПО (РегистрСведенийКодировкиФайлов.Файл = Файлы.Ссылка)
|ГДЕ
| Файлы.СтатусИзвлеченияТекста В (
| ЗНАЧЕНИЕ(Перечисление.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен),
| ЗНАЧЕНИЕ(Перечисление.СтатусыИзвлеченияТекстаФайлов.ПустаяСсылка))";
Иначе
ТекстЗапроса =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Файлы.Ссылка КАК Ссылка,
| ЕСТЬNULL(РегистрСведенийКодировкиФайлов.Кодировка, """") КАК Кодировка
|ИЗ
| &ИмяСправочника КАК Файлы
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КодировкиФайлов КАК РегистрСведенийКодировкиФайлов
| ПО (РегистрСведенийКодировкиФайлов.Файл = Файлы.Ссылка)
|ГДЕ
| Файлы.СтатусИзвлеченияТекста В (
| ЗНАЧЕНИЕ(Перечисление.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен),
| ЗНАЧЕНИЕ(Перечисление.СтатусыИзвлеченияТекстаФайлов.ПустаяСсылка))";
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
Если ИмяСправочника = "ВерсииФайлов" Тогда
ТекстЗапроса = ТекстЗапроса + "
| И НЕ Файлы.Владелец.Зашифрован";
Иначе
ТекстЗапроса = ТекстЗапроса + "
| И НЕ Файлы.Зашифрован";
КонецЕсли;
КонецЕсли;
СтрокаЗамены = ?(ПолучитьВсеФайлы,
"",
"ПЕРВЫЕ " + Формат(ЧислоФайловВВыборке, "ЧГ=; ЧН=")); // @query-part-1
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПЕРВЫЕ 1", СтрокаЗамены);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяСправочника", "Справочник." + ИмяСправочника);
Возврат ТекстЗапроса;
КонецФункции
// Получает полный путь к файлу на диске.
//
// Параметры:
// ОбъектСсылка - ОпределяемыйТип.ПрисоединенныйФайлОбъект - элемент справочника с файлами,
// для которого необходимо получить путь к файлу на диске.
//
// Возвращаемое значение:
// Строка - полный путь к файлу на диске.
//
Функция ИмяФайлаСДвоичнымиДанными(ОбъектСсылка)
ПолноеИмяФайла = "";
Если ОбъектСсылка.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
ХранилищеФайла = РаботаСФайлами.ХранилищеФайлаИзИнформационнойБазы(ОбъектСсылка);
Если ХранилищеФайла = Неопределено Тогда
Возврат "";
КонецЕсли;
ДвоичныеДанныеФайла = ХранилищеФайла.Получить(); //ДвоичныеДанные
Если ТипЗнч(ДвоичныеДанныеФайла) <> Тип("ДвоичныеДанные") Тогда
Возврат "";
КонецЕсли;
ПолноеИмяФайла = ПолучитьИмяВременногоФайла(ОбъектСсылка.Расширение);
ДвоичныеДанныеФайла.Записать(ПолноеИмяФайла);
Иначе
СвойстваФайла = РаботаСФайламиВТомахСлужебный.СвойстваФайлаВТоме();
ЗаполнитьЗначенияСвойств(СвойстваФайла, ОбъектСсылка);
ПолноеИмяФайла = РаботаСФайламиВТомахСлужебный.ПолноеИмяФайлаВТоме(СвойстваФайла);
КонецЕсли;
Возврат ПолноеИмяФайла;
КонецФункции
// Записывает извлеченный текст.
//
// Параметры:
// ТекущаяВерсия - СправочникСсылка.ВерсииФайлов - версия файла.
//
Процедура ПриЗаписиИзвлеченногоТекста(ТекущаяВерсия, ФайлЗаблокирован = Истина)
// Если это не версия, то записываем.
Если ОбщегоНазначения.ЕстьРеквизитОбъекта("ВладелецФайла", Метаданные.НайтиПоТипу(ТипЗнч(ТекущаяВерсия))) Тогда
ОбновлениеИнформационнойБазы.ЗаписатьДанные(ТекущаяВерсия);
Возврат;
КонецЕсли;
Файл = ТекущаяВерсия.Владелец;
ТекущаяВерсияФайла = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Файл, "ТекущаяВерсия");
Если ТекущаяВерсияФайла = ТекущаяВерсия.Ссылка Тогда
Попытка
ЗаблокироватьДанныеДляРедактирования(Файл);
Исключение
ФайлЗаблокирован = Ложь;
ВызватьИсключение;
КонецПопытки;
КонецЕсли;
ОбновлениеИнформационнойБазы.ЗаписатьДанные(ТекущаяВерсия);
Если ТекущаяВерсияФайла = ТекущаяВерсия.Ссылка Тогда
ФайлОбъект = Файл.ПолучитьОбъект();
ФайлОбъект.ТекстХранилище = ТекущаяВерсия.ТекстХранилище;
ОбновлениеИнформационнойБазы.ЗаписатьДанные(ФайлОбъект);
КонецЕсли;
КонецПроцедуры
// Извлекает текст из временного хранилища или из двоичных данных, возвращает статус извлечения.
//
// Параметры:
// АдресВременногоХранилищаТекста - Строка
// ДвоичныеДанные - ДвоичныеДанные
// - Неопределено
// Расширение - Строка
// - Неопределено
//
Функция ИзвлечьТекст(Знач АдресВременногоХранилищаТекста, Знач ДвоичныеДанные = Неопределено, Знач Расширение = Неопределено) Экспорт
УстановитьОтключениеБезопасногоРежима(Истина);
Результат = Новый Структура("СтатусИзвлеченияТекста, ТекстХранилище");
Если ЭтоАдресВременногоХранилища(АдресВременногоХранилищаТекста) Тогда
ИзвлеченныйТекст = СтрокаИзВременногоХранилища(АдресВременногоХранилищаТекста);
Результат.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.Извлечен;
Результат.ТекстХранилище = Новый ХранилищеЗначения(ИзвлеченныйТекст, Новый СжатиеДанных(9));
Возврат Результат;
КонецЕсли;
Если ИзвлекатьТекстыФайловНаСервере() Тогда
Результат.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
Результат.ТекстХранилище = Новый ХранилищеЗначения("");
Возврат Результат; // Текст будет извлечен позднее в регламентном задании.
КонецЕсли;
Если Не ОбщегоНазначения.ЭтоWindowsСервер() Или ДвоичныеДанные = Неопределено Тогда
Результат.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен;
Результат.ТекстХранилище = Новый ХранилищеЗначения("");
Возврат Результат;
КонецЕсли;
// Текст извлекается сразу, а не в регламентном задании.
ИмяВременногоФайла = ПолучитьИмяВременногоФайла(Расширение);
ДвоичныеДанные.Записать(ИмяВременногоФайла);
Результат = ИзвлечьТекстИзФайлаНаДиске(ИмяВременногоФайла);
Попытка
УдалитьФайлы(ИмяВременногоФайла);
Исключение
ЗаписьЖурналаРегистрации(НСтр("ru = 'Файлы.Извлечение текста'", ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Возврат Результат;
КонецФункции
Функция ИзвлечьТекстИзФайлаНаДиске(Знач ИмяФайла, Знач Кодировка = Неопределено) Экспорт
ИзвлеченныйТекст = "";
Результат = Новый Структура("СтатусИзвлеченияТекста, ТекстХранилище");
Результат.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.ИзвлечьНеУдалось;
Попытка
Файл = Новый Файл(ИмяФайла);
Если Не Файл.Существует() Тогда
Возврат Результат;
КонецЕсли;
Исключение
Возврат Результат;
КонецПопытки;
Отказ = Ложь;
ОбщиеНастройки = РаботаСФайламиСлужебныйПовтИсп.НастройкиРаботыСФайлами().ОбщиеНастройки;
РасширениеИмениФайла =
ОбщегоНазначенияКлиентСервер.ПолучитьРасширениеИмениФайла(ИмяФайла);
РасширениеФайлаВСписке = РаботаСФайламиСлужебныйКлиентСервер.РасширениеФайлаВСписке(
ОбщиеНастройки.СписокРасширенийТекстовыхФайлов, РасширениеИмениФайла);
Если РасширениеФайлаВСписке Тогда
ИзвлеченныйТекст = РаботаСФайламиСлужебныйКлиентСервер.ИзвлечьТекстИзТекстовогоФайла(
ИмяФайла, Кодировка, Отказ);
Иначе
Попытка
Извлечение = Новый ИзвлечениеТекста(ИмяФайла);
ИзвлеченныйТекст = Извлечение.ПолучитьТекст();
Исключение
// Когда текст некому извлечь исключение не требуется. Это нормальный случай.
ИзвлеченныйТекст = "";
Отказ = Истина;
КонецПопытки;
Если ПустаяСтрока(ИзвлеченныйТекст) Тогда
РасширениеИмениФайла =
ОбщегоНазначенияКлиентСервер.ПолучитьРасширениеИмениФайла(ИмяФайла);
РасширениеФайлаВСписке = РаботаСФайламиСлужебныйКлиентСервер.РасширениеФайлаВСписке(
ОбщиеНастройки.СписокРасширенийФайловOpenDocument, РасширениеИмениФайла);
Если РасширениеФайлаВСписке Тогда
ИзвлеченныйТекст = РаботаСФайламиСлужебныйКлиентСервер.ИзвлечьТекстOpenDocument(ИмяФайла, Отказ);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если Не Отказ Тогда
Результат.СтатусИзвлеченияТекста = Перечисления.СтатусыИзвлеченияТекстаФайлов.Извлечен;
Результат.ТекстХранилище = Новый ХранилищеЗначения(ИзвлеченныйТекст, Новый СжатиеДанных(9));
КонецЕсли;
Возврат Результат;
КонецФункции
// Получает строку из временного хранилища (передача с клиента на сервер,
// делается через временное хранилище).
//
Функция СтрокаИзВременногоХранилища(АдресВременногоХранилищаТекста)
Если ПустаяСтрока(АдресВременногоХранилищаТекста) Тогда
Возврат "";
КонецЕсли;
ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
ДвоичныеДанныеФайла = ПолучитьИзВременногоХранилища(АдресВременногоХранилищаТекста); //ДвоичныеДанные
ДвоичныеДанныеФайла.Записать(ИмяВременногоФайла);
ТекстовыйФайл = Новый ЧтениеТекста(ИмяВременногоФайла, КодировкаТекста.UTF8);
Текст = ТекстовыйФайл.Прочитать();
ТекстовыйФайл.Закрыть();
Попытка
УдалитьФайлы(ИмяВременногоФайла);
Исключение
ЗаписьЖурналаРегистрации(НСтр("ru = 'Файлы.Извлечение текста'", ОбщегоНазначения.КодОсновногоЯзыка()),
УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Возврат Текст;
КонецФункции
// Параметры:
// ФайлБезТекста - ОпределяемыйТип.ПрисоединенныйФайлОбъект
//
Процедура ИзвлечьТекстИзФайла(ФайлБезТекста, ФайлЗаблокирован, ИмяФайлаСДвоичнымиДанными)
МетаданныеФайла = ФайлБезТекста.Ссылка.Метаданные();
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(МетаданныеФайла.ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлБезТекста.Ссылка);
Если Не ОбщегоНазначения.ЕстьРеквизитОбъекта("ВладелецФайла", МетаданныеФайла) Тогда
Владелец = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ФайлБезТекста.Ссылка, "Владелец");
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Владелец.Метаданные().ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", Владелец);
КонецЕсли;
НачатьТранзакцию();
Попытка
БлокировкаДанных.Заблокировать();
ЗаблокироватьДанныеДляРедактирования(ФайлБезТекста.Ссылка, ИмяФайлаСДвоичнымиДанными);
ФайлЗаблокирован = Истина;
ФайлОбъект = ФайлБезТекста.Ссылка.ПолучитьОбъект();
Если ФайлОбъект <> Неопределено Тогда
Если ЭтоЭлементРаботаСФайлами(ФайлОбъект.Ссылка) Тогда
МетаданныеОбъекта = Метаданные.НайтиПоТипу(ТипЗнч(ФайлОбъект.Ссылка));
ВозможностьХранитьВерсии = ОбщегоНазначения.ЕстьРеквизитОбъекта("ТекущаяВерсия", МетаданныеОбъекта);
Если ВозможностьХранитьВерсии И ЗначениеЗаполнено(ФайлОбъект.ТекущаяВерсия.Ссылка) Тогда
ИмяФайлаСДвоичнымиДанными = ИмяФайлаСДвоичнымиДанными(ФайлОбъект.ТекущаяВерсия.Ссылка);
Иначе
ИмяФайлаСДвоичнымиДанными = ИмяФайлаСДвоичнымиДанными(ФайлОбъект.Ссылка);
КонецЕсли;
КонецЕсли;
Если ПустаяСтрока(ИмяФайлаСДвоичнымиДанными) Тогда
РазблокироватьДанныеДляРедактирования(ФайлБезТекста.Ссылка);
ФайлЗаблокирован = Ложь;
Иначе
РезультатИзвлеченияТекста = ИзвлечьТекстИзФайлаНаДиске(ИмяФайлаСДвоичнымиДанными, ФайлБезТекста.Кодировка);
ФайлОбъект.СтатусИзвлеченияТекста = РезультатИзвлеченияТекста.СтатусИзвлеченияТекста;
ФайлОбъект.ТекстХранилище = РезультатИзвлеченияТекста.ТекстХранилище;
ПриЗаписиИзвлеченногоТекста(ФайлОбъект, ФайлЗаблокирован);
Если ФайлОбъект.ТипХраненияФайла <> Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе Тогда
ИмяФайлаСДвоичнымиДанными = "";
КонецЕсли;
КонецЕсли;
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиПодписокНаСобытия
// Обработчик подписки "при записи" версии файла.
//
// Параметры:
// Источник - СправочникОбъект.ВерсииФайлов
//
Процедура ВерсииФайловПриЗаписи(Источник, Отказ) Экспорт
Если Источник.ОбменДанными.Загрузка Тогда
ЗаписатьДанныеФайлаВРегистрПриОбмене(Источник);
Возврат;
КонецЕсли;
Если Источник.ДополнительныеСвойства.Свойство("ПереименованиеФайла")
Или Источник.ДополнительныеСвойства.Свойство("КонвертацияФайлов") Тогда
Возврат;
КонецЕсли;
// Копируем реквизиты из версии в файл.
ТекущаяВерсия = Источник;
Если Не ТекущаяВерсия.Ссылка.Пустая() Тогда
ФайлСсылка = Источник.Владелец;
РеквизитыФайла = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(ФайлСсылка,
"ТекущаяВерсия, ИндексКартинки, Размер, ДатаСоздания, Изменил, Расширение, Том, ПутьКФайлу, ДатаМодификацииУниверсальная");
Если РеквизитыФайла.Размер <> ТекущаяВерсия.Размер
ИЛИ РеквизитыФайла.ДатаСоздания <> ТекущаяВерсия.ДатаСоздания
ИЛИ РеквизитыФайла.Расширение <> ТекущаяВерсия.Расширение
ИЛИ РеквизитыФайла.Том <> ТекущаяВерсия.Том
ИЛИ РеквизитыФайла.ПутьКФайлу <> ТекущаяВерсия.ПутьКФайлу
ИЛИ РеквизитыФайла.ИндексКартинки <> ТекущаяВерсия.ИндексКартинки
ИЛИ РеквизитыФайла.ДатаМодификацииУниверсальная <> ТекущаяВерсия.ДатаМодификацииФайла Тогда
НачатьТранзакцию();
Попытка
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.НайтиПоТипу(ТипЗнч(ФайлСсылка)).ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("Ссылка", ФайлСсылка);
БлокировкаДанных.Заблокировать();
ФайлОбъект = ФайлСсылка.ПолучитьОбъект();
// Сменим индекс картинки, возможно, появилась версия или сменился индекс картинки у версии.
ФайлОбъект.ИндексКартинки = ТекущаяВерсия.ИндексКартинки;
// Копируем реквизиты для ускорения работы ограничения на уровне записей.
ФайлОбъект.Размер = ТекущаяВерсия.Размер;
ФайлОбъект.ДатаСоздания = ТекущаяВерсия.ДатаСоздания;
ФайлОбъект.Изменил = ТекущаяВерсия.Автор;
ФайлОбъект.Расширение = ТекущаяВерсия.Расширение;
ФайлОбъект.Том = ТекущаяВерсия.Том;
ФайлОбъект.ПутьКФайлу = ТекущаяВерсия.ПутьКФайлу;
ФайлОбъект.ТипХраненияФайла = ТекущаяВерсия.ТипХраненияФайла;
ФайлОбъект.ДатаМодификацииУниверсальная = ТекущаяВерсия.ДатаМодификацииУниверсальная;
Если Источник.ДополнительныеСвойства.Свойство("ЗаписьПодписанногоОбъекта") Тогда
ФайлОбъект.ДополнительныеСвойства.Вставить("ЗаписьПодписанногоОбъекта",
Источник.ДополнительныеСвойства.ЗаписьПодписанногоОбъекта);
КонецЕсли;
// Проверка прав доступа не требуется.
УстановитьПривилегированныйРежим(Истина);
ФайлОбъект.Записать();
УстановитьПривилегированныйРежим(Ложь);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецЕсли;
КонецЕсли;
ОбновитьСостояниеОчередиИзвлеченияТекста(Источник.Ссылка, Источник.СтатусИзвлеченияТекста);
КонецПроцедуры
// Обработчик подписки на событие "Перед удалением" присоединенного файла.
Процедура ПередУдалениемПрисоединенногоФайлаСервер(Знач Ссылка,
Знач ВладелецФайлов,
Знач Том,
Знач ТипХраненияФайла,
Знач ПутьКФайлу) Экспорт
УстановитьПривилегированныйРежим(Истина);
Если ВладелецФайлов <> Неопределено И Не ЕстьФайлыУВладельца(ВладелецФайлов, Ссылка) Тогда
НачатьТранзакцию();
Попытка
БлокировкаДанных = Новый БлокировкаДанных;
ЭлементБлокировкиДанных = БлокировкаДанных.Добавить(Метаданные.РегистрыСведений.НаличиеФайлов.ПолноеИмя());
ЭлементБлокировкиДанных.УстановитьЗначение("ОбъектСФайлами", ВладелецФайлов);
БлокировкаДанных.Заблокировать();
МенеджерЗаписи = РегистрыСведений.НаличиеФайлов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ОбъектСФайлами = ВладелецФайлов;
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
МенеджерЗаписи.ЕстьФайлы = Ложь;
МенеджерЗаписи.Записать();
КонецЕсли;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецЕсли;
Если ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске
И Не Том.Пустая() Тогда
СвойстваФайла = РаботаСФайламиВТомахСлужебный.СвойстваФайлаВТоме(Ссылка);
РаботаСФайламиВТомахСлужебный.УдалитьФайл(
РаботаСФайламиВТомахСлужебный.ПолноеИмяФайлаВТоме(СвойстваФайла));
КонецЕсли;
КонецПроцедуры
// Проверяет право текущего пользователя
// при использовании ограничения для папки или файла.
//
// Параметры:
// Право - Строка - имя права.
// ВладелецПрав - СправочникСсылка.ПапкиФайлов
// - СправочникСсылка.Файлы
// - ОпределяемыйТип.ВладелецПрисоединенныхФайлов
//
Функция ЕстьПраво(Право, ВладелецПрав) Экспорт
Если Не ЭтоПапкаФайлов(ВладелецПрав) Тогда
Возврат Истина;
КонецЕсли;
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
Если НЕ МодульУправлениеДоступом.ЕстьПраво(Право, ВладелецПрав) Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
Возврат Истина;
КонецФункции
// Обработчик подписки "Обработка проверки заполнения" присоединенного файла.
//
Процедура ОбработкаПроверкиЗаполненияПрисоединенногоФайла(Источник, Отказ) Экспорт
Если Источник.ДополнительныеСвойства.Свойство("ОтложеннаяЗапись")
И РаботаСФайлами.ДвоичныеДанныеФайла(Источник.Ссылка, Ложь) = Неопределено Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Функция ЕстьФайлыУВладельца(Знач ВладелецФайлов, Знач ФайлИсключение = Неопределено)
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.Параметры.Вставить("ВладелецФайлов", ВладелецФайлов);
ТекстЗапроса =
"ВЫБРАТЬ
| ПрисоединенныеФайлы.Ссылка
|ИЗ
| &ИмяСправочника КАК ПрисоединенныеФайлы
|ГДЕ
| ПрисоединенныеФайлы.ВладелецФайла = &ВладелецФайлов";
Если ФайлИсключение <> Неопределено Тогда
ТекстЗапроса = ТекстЗапроса + "
| И ПрисоединенныеФайлы.Ссылка <> &Ссылка";
Запрос.Параметры.Вставить("Ссылка", ФайлИсключение);
КонецЕсли;
ИменаСправочников = ИменаСправочниковХраненияФайлов(ВладелецФайлов);
Для каждого КлючИЗначение Из ИменаСправочников Цикл
Запрос.Текст = СтрЗаменить(
ТекстЗапроса, "&ИмяСправочника", "Справочник." + КлючИЗначение.Ключ);
Если НЕ Запрос.Выполнить().Пустой() Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
#КонецОбласти
#Область ОбновлениеИнформационнойБазы
Процедура ОбновитьСписокЗапрещенныхРасширений() Экспорт
СписокЗапрещенныхРасширенийДляЗагрузки = СписокЗапрещенныхРасширений();
СписокЗапрещенныхРасширенийВБазе = Константы.СписокЗапрещенныхРасширений.Получить();
МассивЗапрещенныхРасширений = СтрРазделить(СписокЗапрещенныхРасширенийВБазе, " ");
ОбновитьСписокЗапрещенныхРасширений = Ложь;
Для Каждого Расширение Из СписокЗапрещенныхРасширенийДляЗагрузки Цикл
Если МассивЗапрещенныхРасширений.Найти(ВРег(Расширение)) = Неопределено Тогда
ОбновитьСписокЗапрещенныхРасширений = Истина;
МассивЗапрещенныхРасширений.Добавить(ВРег(Расширение));
КонецЕсли;
КонецЦикла;
СписокЗапрещенныхРасширенийВБазе = СтрСоединить(МассивЗапрещенныхРасширений, " ");
Если ОбновитьСписокЗапрещенныхРасширений Тогда
Константы.СписокЗапрещенныхРасширений.Установить(СписокЗапрещенныхРасширенийВБазе);
КонецЕсли;
КонецПроцедуры
Процедура ОбновитьСписокЗапрещенныхРасширенийВОбластиДанных() Экспорт
СписокЗапрещенныхРасширенийДляЗагрузки = СписокЗапрещенныхРасширений();
ОбновитьСписокЗапрещенныхРасширенийОбластиДанных = Ложь;
СписокЗапрещенныхРасширенийОбластиДанных = Константы.СписокЗапрещенныхРасширенийОбластиДанных.Получить();
МассивЗапрещенныхРасширенийОбластиДанных = СтрРазделить(СписокЗапрещенныхРасширенийОбластиДанных, " ");
Для Каждого Расширение Из СписокЗапрещенныхРасширенийДляЗагрузки Цикл
Если МассивЗапрещенныхРасширенийОбластиДанных.Найти(ВРег(Расширение)) = Неопределено Тогда
МассивЗапрещенныхРасширенийОбластиДанных.Добавить(ВРег(Расширение));
ОбновитьСписокЗапрещенныхРасширенийОбластиДанных = Истина;
КонецЕсли;
КонецЦикла;
СписокЗапрещенныхРасширенийОбластиДанных = СтрСоединить(МассивЗапрещенныхРасширенийОбластиДанных, " ");
Если ОбновитьСписокЗапрещенныхРасширенийОбластиДанных Тогда
Константы.СписокЗапрещенныхРасширенийОбластиДанных.Установить(СписокЗапрещенныхРасширенийОбластиДанных);
КонецЕсли;
КонецПроцедуры
Процедура ОбновитьСписокРасширенийТекстовыхФайлов() Экспорт
СписокРасширений = Константы.СписокРасширенийТекстовыхФайлов.Получить();
РасширенияТекстовыхФайлов = СтрРазделить(СписокРасширений, " ");
ОбновитьСписокРасширений = Ложь;
Для Каждого Расширение Из СтрРазделить(СписокРасширенийТекстовыхФайлов(), " ") Цикл
Если РасширенияТекстовыхФайлов.Найти(ВРег(Расширение)) = Неопределено Тогда
ОбновитьСписокРасширений = Истина;
РасширенияТекстовыхФайлов.Добавить(ВРег(Расширение));
КонецЕсли;
КонецЦикла;
Если ОбновитьСписокРасширений Тогда
Константы.СписокРасширенийТекстовыхФайлов.Установить(СтрСоединить(РасширенияТекстовыхФайлов, " "));
КонецЕсли;
КонецПроцедуры
// Удаляет запись в регистре ХранимыеФайлыВерсий.
//
// Параметры:
// Файл - ОпределяемыйТип.ПрисоединенныйФайл - ссылка на файл.
//
Процедура УдалитьЗаписьИзРегистраДвоичныеДанныеФайлов(Файл) Экспорт
УстановитьПривилегированныйРежим(Истина);
НаборЗаписей = РегистрыСведений.ДвоичныеДанныеФайлов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Файл.Установить(Файл);
НаборЗаписей.Записать();
КонецПроцедуры
// Получает количество версий с неизвлеченным текстом.
Процедура ПолучитьКоличествоВерсийСНеизвлеченнымТекстом(ДополнительныеПараметры, АдресВоВременномХранилище) Экспорт
КоличествоФайлов = 0;
ТипыФайлов = Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип.Типы();
Для Каждого Тип Из ТипыФайлов Цикл
МетаданныеСправочникаФайлов = Метаданные.НайтиПоТипу(Тип);
Запрос = Новый Запрос;
ТекстЗапроса =
"ВЫБРАТЬ
| ЕСТЬNULL(КОЛИЧЕСТВО(Файлы.Ссылка), 0) КАК КоличествоФайлов
|ИЗ
| &ИмяСправочника КАК Файлы
|ГДЕ
| Файлы.СтатусИзвлеченияТекста В (ЗНАЧЕНИЕ(Перечисление.СтатусыИзвлеченияТекстаФайлов.НеИзвлечен), ЗНАЧЕНИЕ(Перечисление.СтатусыИзвлеченияТекстаФайлов.ПустаяСсылка))";
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ЭлектроннаяПодпись") Тогда
Если Тип = Тип("СправочникСсылка.ВерсииФайлов") Тогда
ТекстЗапроса = ТекстЗапроса + "
| И НЕ Файлы.Владелец.Зашифрован";
Иначе
ТекстЗапроса = ТекстЗапроса + "
| И НЕ Файлы.Зашифрован";
КонецЕсли;
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяСправочника", "Справочник." + МетаданныеСправочникаФайлов.Имя);
Запрос.Текст = ТекстЗапроса;
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
КоличествоФайлов = КоличествоФайлов + Выборка.КоличествоФайлов;
КонецЕсли
КонецЦикла;
ПоместитьВоВременноеХранилище(КоличествоФайлов, АдресВоВременномХранилище);
КонецПроцедуры
// Регистрирует на плане обмена ОбновлениеИнформационнойБазы объекты,
// для которых необходимо обновить записи в реестре.
//
Процедура ЗарегистрироватьОбъектыДляПереносаЭлектронныхПодписейИСертификатовШифрования(Параметры) Экспорт
ТекстЗапросаДвеТабличныеЧасти =
"ВЫБРАТЬ
| Файлы.Ссылка КАК Ссылка
|ИЗ
| ТаблицаОбъектов КАК Файлы
|ГДЕ
| (ИСТИНА В
| (ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ТабличнаяЧастьУдалитьСертификатыШифрования КАК УдалитьСертификатыШифрования
| ГДЕ
| УдалитьСертификатыШифрования.Ссылка = Файлы.Ссылка)
| ИЛИ ИСТИНА В
| (ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ТабличнаяЧастьУдалитьЭлектронныеПодписи КАК УдалитьЭлектронныеПодписи
| ГДЕ
| УдалитьЭлектронныеПодписи.Ссылка = Файлы.Ссылка))";
ТекстЗапросаТЧУдалитьСертификатыШифрования =
"ВЫБРАТЬ
| Файлы.Ссылка КАК Ссылка
|ИЗ
| ТаблицаОбъектов КАК Файлы
|ГДЕ
| ИСТИНА В
| (ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ТабличнаяЧастьУдалитьСертификатыШифрования КАК УдалитьСертификатыШифрования
| ГДЕ
| УдалитьСертификатыШифрования.Ссылка = Файлы.Ссылка)";
ТекстЗапросаТЧУдалитьЭлектронныеПодписи =
"ВЫБРАТЬ
| Файлы.Ссылка КАК Ссылка
|ИЗ
| ТаблицаОбъектов КАК Файлы
|ГДЕ
| ИСТИНА В
| (ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| ТабличнаяЧастьУдалитьЭлектронныеПодписи КАК УдалитьЭлектронныеПодписи
| ГДЕ
| УдалитьЭлектронныеПодписи.Ссылка = Файлы.Ссылка)";
Запрос = Новый Запрос;
ПолныеИменаСправочников = ПолныеИменаСправочниковПрисоединенныхФайлов();
Для Каждого ПолноеИмя Из ПолныеИменаСправочников Цикл
ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмя);
ЕстьТЧУдалитьСертификатыШифрования =
ОбъектМетаданных.ТабличныеЧасти.Найти("УдалитьСертификатыШифрования") <> Неопределено;
ЕстьТЧУдалитьЭлектронныеПодписи =
ОбъектМетаданных.ТабличныеЧасти.Найти("УдалитьЭлектронныеПодписи") <> Неопределено;
Если ЕстьТЧУдалитьСертификатыШифрования И ЕстьТЧУдалитьЭлектронныеПодписи Тогда
ТекущийТекстЗапроса = ТекстЗапросаДвеТабличныеЧасти;
ИначеЕсли ЕстьТЧУдалитьСертификатыШифрования Тогда
ТекущийТекстЗапроса = ТекстЗапросаТЧУдалитьСертификатыШифрования;
ИначеЕсли ЕстьТЧУдалитьЭлектронныеПодписи Тогда
ТекущийТекстЗапроса = ТекстЗапросаТЧУдалитьЭлектронныеПодписи;
Иначе
Продолжить;
КонецЕсли;
Если ЗначениеЗаполнено(Запрос.Текст) Тогда
Запрос.Текст = Запрос.Текст + "
|
|ОБЪЕДИНИТЬ ВСЕ
|
|";
КонецЕсли;
ТекущийТекстЗапроса = СтрЗаменить(ТекущийТекстЗапроса, "ТаблицаОбъектов", ПолноеИмя);
ТекущийТекстЗапроса = СтрЗаменить(ТекущийТекстЗапроса,
"ТабличнаяЧастьУдалитьСертификатыШифрования", ПолноеИмя + ".УдалитьСертификатыШифрования");
ТекущийТекстЗапроса = СтрЗаменить(ТекущийТекстЗапроса,
"ТабличнаяЧастьУдалитьЭлектронныеПодписи", ПолноеИмя + ".УдалитьЭлектронныеПодписи");
Запрос.Текст = Запрос.Текст + ТекущийТекстЗапроса;
КонецЦикла;
МассивСсылок = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
ОбновлениеИнформационнойБазы.ОтметитьКОбработке(Параметры, МассивСсылок);
КонецПроцедуры
Процедура ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведений(Параметры) Экспорт
ОбработкаЗавершена = Истина;
ПолныеИменаСправочников = ПолныеИменаСправочниковПрисоединенныхФайлов();
Для Каждого ПолноеИмяСправочника Из ПолныеИменаСправочников Цикл
ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведенийДляТаблицы(Параметры,
ПолноеИмяСправочника, ОбработкаЗавершена);
КонецЦикла;
Параметры.ОбработкаЗавершена = ОбработкаЗавершена;
КонецПроцедуры
// Позволяет перенести элементы табличных частей УдалитьЭлектронныеПодписи и УдалитьСертификатыШифрования
// в регистры сведений ЭлектронныеПодписи и СертификатыШифрования.
//
// Параметры:
// ПараметрыОбновления - Структура - структура параметров отложенного обработчика обновления.
//
// ПолноеИмяОбъектаМетаданных - Строка - полное имя объекта метаданных, из которого переносятся данные табличных частей
// УдалитьЭлектронныеПодписи и УдалитьСертификатыШифрования.
// ОбработкаЗавершена - Булево - Истина, если обработаны все данные при обновлении ИБ.
//
Процедура ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведенийДляТаблицы(ПараметрыОбновления, ПолноеИмяОбъектаМетаданных, ОбработкаЗавершена)
ОбъектМетаданных = Метаданные.НайтиПоПолномуИмени(ПолноеИмяОбъектаМетаданных);
Если ОбъектМетаданных = Неопределено Тогда
ВызватьИсключение НСтр("ru = 'Не указан объект для обработки электронных подписей и сертификатов шифрования.'");
КонецЕсли;
ЕстьТабличнаяЧастьЭП = ОбъектМетаданных.ТабличныеЧасти.Найти("УдалитьЭлектронныеПодписи") <> Неопределено;
ЕстьТабличнаяЧастьСШ = ОбъектМетаданных.ТабличныеЧасти.Найти("УдалитьСертификатыШифрования") <> Неопределено;
ВыборкаСсылок = ОбновлениеИнформационнойБазы.ВыбратьСсылкиДляОбработки(ПараметрыОбновления.Очередь, ПолноеИмяОбъектаМетаданных);
ОбъектовОбработано = 0;
ПроблемныхОбъектов = 0;
МассивСсылок = Новый Массив;
НачатьТранзакцию();
Попытка
Пока ВыборкаСсылок.Следующий() Цикл
МассивСсылок.Добавить(ВыборкаСсылок.Ссылка);
КонецЦикла;
Если ЕстьТабличнаяЧастьЭП Тогда
ПеренестиДанныеЭлектроннойПодписиВРегистрСведений(МассивСсылок,
ПолноеИмяОбъектаМетаданных, ОбъектМетаданных);
КонецЕсли;
Если ЕстьТабличнаяЧастьСШ Тогда
ПеренестиДанныеСертификатовВРегистрСведений(МассивСсылок, ПолноеИмяОбъектаМетаданных);
КонецЕсли;
Для Каждого ОбъектСЭП Из МассивСсылок Цикл
ОбновлениеИнформационнойБазы.ОтметитьВыполнениеОбработки(ОбъектСЭП);
КонецЦикла;
ОбъектовОбработано = МассивСсылок.Количество();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
// Если не удалось обработать какой-либо объект, требуется повторить попытку.
ПроблемныхОбъектов = ПроблемныхОбъектов + МассивСсылок.Количество();
ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось обработать объект: %1 по причине:
|%2'"),
ОбъектМетаданных,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ЗаписьЖурналаРегистрации(ОбновлениеИнформационнойБазы.СобытиеЖурналаРегистрации(),
УровеньЖурналаРегистрации.Предупреждение, ОбъектМетаданных, , ТекстСообщения);
КонецПопытки;
Если Не ОбновлениеИнформационнойБазы.ОбработкаДанныхЗавершена(ПараметрыОбновления.Очередь, ПолноеИмяОбъектаМетаданных) Тогда
ОбработкаЗавершена = Ложь;
КонецЕсли;
Если ОбъектовОбработано = 0 И ПроблемныхОбъектов <> 0 Тогда
ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Процедуре ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведений не удалось обработать некоторые объекты (пропущены): %1'"),
ПроблемныхОбъектов);
ВызватьИсключение ТекстСообщения;
Иначе
ЗаписьЖурналаРегистрации(ОбновлениеИнформационнойБазы.СобытиеЖурналаРегистрации(),
УровеньЖурналаРегистрации.Информация,
ОбъектМетаданных,
,
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Процедура ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведений обработала очередную порцию объектов: %1'"),
ОбъектовОбработано));
КонецЕсли;
КонецПроцедуры
// Для процедуры ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведенийДляТаблицы.
Процедура ПеренестиДанныеЭлектроннойПодписиВРегистрСведений(МассивОбъектов, ПолноеИмяОбъектаМетаданных, ОбъектМетаданных)
УстановитьПривилегированныйРежим(Истина);
Блокировка = Новый БлокировкаДанных;
Для Каждого ОбъектСДанными Из МассивОбъектов Цикл
ЭлементБлокировки = Блокировка.Добавить(ПолноеИмяОбъектаМетаданных);
ЭлементБлокировки.УстановитьЗначение("Ссылка", ОбъектСДанными);
КонецЦикла;
НачатьТранзакцию();
Попытка
Блокировка.Заблокировать();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТЧЭлектронныеПодписи.Ссылка КАК ПодписанныйОбъект,
| ТЧЭлектронныеПодписи.ДатаПодписи,
| ТЧЭлектронныеПодписи.ИмяФайлаПодписи,
| ТЧЭлектронныеПодписи.Комментарий,
| ТЧЭлектронныеПодписи.КомуВыданСертификат,
| ТЧЭлектронныеПодписи.Отпечаток,
| ТЧЭлектронныеПодписи.Подпись,
| ТЧЭлектронныеПодписи.УстановившийПодпись,
| ТЧЭлектронныеПодписи.НомерСтроки КАК ПорядковыйНомер,
| ТЧЭлектронныеПодписи.Сертификат,
| ТЧЭлектронныеПодписи.ПодписьВерна КАК ПодписьВерна,
| ТЧЭлектронныеПодписи.ДатаПроверкиПодписи КАК ДатаПроверкиПодписи
|ИЗ
| &УдалитьЭлектронныеПодписи КАК ТЧЭлектронныеПодписи
|ГДЕ
| ТЧЭлектронныеПодписи.Ссылка В(&МассивОбъектов)
|ИТОГИ
| ПО ПодписанныйОбъект";
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УдалитьЭлектронныеПодписи", ПолноеИмяОбъектаМетаданных + ".УдалитьЭлектронныеПодписи");
Если ОбъектМетаданных = Метаданные.Справочники.ВерсииФайлов Тогда
Запрос.Текст = СтрЗаменить(Запрос.Текст,
"ТЧЭлектронныеПодписи.Ссылка КАК ПодписанныйОбъект",
"ТЧЭлектронныеПодписи.Ссылка.Владелец КАК ПодписанныйОбъект");
КонецЕсли;
РеквизитыТЧ = ОбъектМетаданных.ТабличныеЧасти.УдалитьЭлектронныеПодписи.Реквизиты;
Если РеквизитыТЧ.Найти("ПодписьВерна") = Неопределено Тогда
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ТЧЭлектронныеПодписи.ПодписьВерна", "ЛОЖЬ");
КонецЕсли;
Если РеквизитыТЧ.Найти("ДатаПроверкиПодписи") = Неопределено Тогда
Запрос.Текст = СтрЗаменить(Запрос.Текст, "ТЧЭлектронныеПодписи.ДатаПроверкиПодписи", "Неопределено");
КонецЕсли;
Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
Выгрузка = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
Для Каждого Строка Из Выгрузка.Строки Цикл
Если Не ЗначениеЗаполнено(Строка.ПодписанныйОбъект) Тогда
Продолжить;
КонецЕсли;
НаборЗаписей = РегистрыСведений["ЭлектронныеПодписи"].СоздатьНаборЗаписей(); //РегистрСведенийНаборЗаписей
НаборЗаписей.Отбор.ПодписанныйОбъект.Установить(Строка.ПодписанныйОбъект);
Для Каждого Подстрока Из Строка.Строки Цикл
ЗаполнитьЗначенияСвойств(НаборЗаписей.Добавить(), Подстрока);
КонецЦикла;
// Используется параллельное обновление с нестандартной отметкой выполнения обработанных данных.
НаборЗаписей.ОбменДанными.Загрузка = Истина;
НаборЗаписей.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов");
НаборЗаписей.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
НаборЗаписей.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
// Для процедуры ПеренестиЭлектронныеПодписиИСертификатыШифрованияВРегистрыСведенийДляТаблицы.
Процедура ПеренестиДанныеСертификатовВРегистрСведений(МассивОбъектов, ПолноеИмяОбъектаМетаданных)
УстановитьПривилегированныйРежим(Истина);
Блокировка = Новый БлокировкаДанных;
Для Каждого ОбъектСДанными Из МассивОбъектов Цикл
ЭлементБлокировки = Блокировка.Добавить(ПолноеИмяОбъектаМетаданных);
ЭлементБлокировки.УстановитьЗначение("Ссылка", ОбъектСДанными);
КонецЦикла;
НачатьТранзакцию();
Попытка
Блокировка.Заблокировать();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТЧСертификатыШифрования.Ссылка КАК ЗашифрованныйОбъект,
| ТЧСертификатыШифрования.Отпечаток,
| ТЧСертификатыШифрования.Сертификат,
| ТЧСертификатыШифрования.НомерСтроки КАК ПорядковыйНомер,
| ТЧСертификатыШифрования.Представление
|ИЗ
| &УдалитьСертификатыШифрования КАК ТЧСертификатыШифрования
|ГДЕ
| ТЧСертификатыШифрования.Ссылка В(&МассивОбъектов)
|ИТОГИ
| ПО ЗашифрованныйОбъект";
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УдалитьСертификатыШифрования",
ПолноеИмяОбъектаМетаданных + ".УдалитьСертификатыШифрования");
Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);
Выгрузка = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
Для Каждого Строка Из Выгрузка.Строки Цикл
НаборЗаписей = РегистрыСведений["СертификатыШифрования"].СоздатьНаборЗаписей(); //РегистрСведенийНаборЗаписей
НаборЗаписей.Отбор.ЗашифрованныйОбъект.Установить(Строка.ЗашифрованныйОбъект);
Для Каждого Подстрока Из Строка.Строки Цикл
ЗаполнитьЗначенияСвойств(НаборЗаписей.Добавить(), Подстрока);
КонецЦикла;
// Используется параллельное обновление с нестандартной отметкой выполнения обработанных данных.
НаборЗаписей.ОбменДанными.Загрузка = Истина;
НаборЗаписей.ДополнительныеСвойства.Вставить("ОтключитьМеханизмРегистрацииОбъектов");
НаборЗаписей.ОбменДанными.Получатели.АвтоЗаполнение = Ложь;
НаборЗаписей.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Функция ПолныеИменаСправочниковПрисоединенныхФайлов()
Массив = Новый Массив;
Для Каждого ТипПрисоединенногоФайла Из Метаданные.ОпределяемыеТипы.ПрисоединенныйФайл.Тип.Типы() Цикл
ПолноеИмя = Метаданные.НайтиПоТипу(ТипПрисоединенногоФайла).ПолноеИмя();
Если СтрЗаканчиваетсяНа(ВРег(ПолноеИмя), ВРег("ВерсииПрисоединенныхФайлов")) Тогда
Продолжить;
КонецЕсли;
Массив.Добавить(Метаданные.НайтиПоТипу(ТипПрисоединенногоФайла).ПолноеИмя());
КонецЦикла;
Если Массив.Найти("Справочник.Файлы") = Неопределено Тогда
Массив.Добавить("Справочник.Файлы");
КонецЕсли;
Если Массив.Найти("Справочник.ВерсииФайлов") = Неопределено Тогда
Массив.Добавить("Справочник.ВерсииФайлов");
КонецЕсли;
Возврат Массив;
КонецФункции
Функция ИзменяемыеОбъектыПриПереносеЭлектронныхПодписейИСертификатовШифрования()
Возврат Метаданные.РегистрыСведений["ЭлектронныеПодписи"].ПолноеИмя() + ", "
+ Метаданные.РегистрыСведений["СертификатыШифрования"].ПолноеИмя();
КонецФункции
#КонецОбласти
#КонецОбласти