Организация простейшего внешнего хранилища прикрепленных к документу (элементу справочника, …) файлов на web-сервере, или не засоряем базу 1С

Если Вы ощущаете когнитивный диссонанс, когда сталкиваетесь с многогигабайтной базой данных, забитой разношёрстными файлами хранилища дополнительной информации, и Вас, как и меня, не устраивает сама идея хранения бинарных файлов в базе данных, то эта статья, возможно, окажется полезной.

Для решения проблемы с неприличным объёмом базы данных 1C из-за хранения в ней приложенных файлов в справочнике типа «ХранилищеДополнительнойИнформации» и всех вытекающих из этого неудобств, таких как огромного размера выгрузки ИБ и файла бэкапов, было написано следующее. (Данное решение не претендует на замену встроенных механизмов хранения файлов в конфигурациях типа «документооборот» без соответствующей доработки, однако, ничто не мешает доработать описанный принцип под конкретные нужды.)

Принцип довольно прост:

  • Добавляем на форму нужного объекта HTML-поле, в котором будет отображаться web-интерфейс файлового менеджера (по-моему, ограничений на платформу здесь нет, HTML на форме можно было и в 7.7 отобразить, поправьте, если не прав),
  • Берём любой понравившийся web- файловый менеджер, и ставим его на web-сервер (в данной статье как пример взят и изменен под свои нужды дистрибутив простого php файлового менеджера Sabre (изменённая версия на github) как web сервер использовался WAMP с основной кодировкой utf-8. Также все отлчино работает на LAMP. Версия php — предпочитаю свежую, но, возможно, Sabre будет работать и на 5.3 и ниже.)
  • При открытии формы объекта, отображаем на нашей форме файл-менеджер, вызванный с определенными GET-параметрами (например, относительный путь к папке, формируемый из имени и номера объекта). Также, если нужно, можно сделать разделение по ролям, кому можно удалятьредактироватьпросматривать, кому — нет и вместо передачи простых GET-запросов хоть XML или JSON через POST и авторизацию прикрутить, как душе угодно)
  • В итоге пользователь может скачивать и прикреплять файлы, подробности процесса остаются для него не очевидными, а сами файлы лежат себе на том же (или другом) сервере в определенном месте, удобно распределенные по папкам — напр. /Документ/325/файл_документа_325.pdf и не захламляют базу.

Реализация:

Рассмотрим довольно простую и быструю реализацию задумки на примере WAMP:

устанавливаем последнюю версию web-сервера (допустим, в папку d:wamp) Чтобы можно было загружать файлы до 100 мегабайт изменяем php.ini в d:wampinapacheapache_ВЕРСИЯ_in

...
post_max_size = 100M
...
upload_max_filesize = 100M
...

Чтобы сервис стартовал автоматически, запускаем services.msc, ищем wampapache64 (если x64) и ставим тип запуска — «Автоматически»

Важно! Чтобы wampmanager.exe при выходе не завершал заодно и работу web-сервера, что, сами понимаете чем чревато, изменяем wampmanager.tpl и wampmanager.ini предварительно завершив wampmanager.exe. Ищем блок [myexit] и комментируем нежелательные действия: wampmanager.ini:

[myexit]
;WAMPMYEXITSTART
;Action: service; Service: wampapache64; ServiceAction: stop; Flags: ignoreerrors
;Action: service; Service: wampmysqld64; ServiceAction: stop; Flags: ignoreerrors
Action:  exit
;WAMPMYEXITEND

wampmanager.tpl:

[myexit]
;WAMPMYEXITSTART
;Action: service; Service: ${c_apacheService}; ServiceAction: stop; Flags: ignoreerrors
;Action: service; Service: ${c_mysqlService}; ServiceAction: stop; Flags: ignoreerrors
Action:  exit
;WAMPMYEXITEND

Далее распаковываем в папку d:wampwww изменённую вверсия Sabre с github, переходим в браузере на http://localhost/Sabre1c-master/install/ и настраиваем как пожелаем. Создаём папку для загрузок, какую указали (по-умолчанию upload) в d:wampwwwSabre1c-master переходим на http://localhost/Sabre1c-master/?CWD=Тест123 и загружаем любой файл, проверяем результат в папке d:wampwwwSabre1c-masteruploadТест123 появился загруженный файл.

Работу файл-менеджера проверял как на windows, так и на linux web-серверах, проблем с кодировкой имени файла при загрузкескачивании удалось избежать. Пробелы в имени файла при загрузке заменяются символами нижнего подчёркивания. Если есть необходимость запретить загружать файлы с расширением, не включенным в список разрешенных, можно раскоментировать и попровить несколько строк в файле coreupload.php:

 $ext_allowed = array('txt', 'jpg', 'pdf', 'zip', 'png');
if(!in_array(strtolower($extension), $ext_allowed)){
header('location: ../?action=upload&file=');
exit;
}

Теперь идём в 1с и размещаем на нужном документе или справочнике ПолеHTMLДокумента с аналогичным именем и добавляем в функцию модуля ПриОткрытии() код:

// пример для обычных форм 8.X, Документ
Процедура ПриОткрытии(Отказ) {
Если ДокументОбъект.Номер Тогда
ЭлементыФормы.ПолеHTMLДокумента.Видимость=Истина;
// если у вас числовая нумерация, Адрес="http://localhost/Sabre1c-master/?CWD="+"/"+ДокументОбъект.Метаданные().Имя+"/"+Формат(ДокументОбъект.Номер,"ЧГ=0");
Адрес="http://localhost/Sabre1c-master/?CWD="+"/"+ДокументОбъект.Метаданные().Имя+"/"+ДокументОбъект.Номер;
ЭлементыФормы.ПолеHTMLДокумента.Документ.URL = Адрес;
КонецЕсли;
КонецПроцедуры

// пример для управляемых форм 8.X, Справочник
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Объект.Код Тогда
Элементы.ПолеHTMLДокумента.Видимость=Истина;
// если у вас числовая нумерация, Адрес="localhost/Sabre1c-master/?CWD="+"/contacts/"+Формат(Объект.Код,"ЧГ=0");
Адрес="localhost/Sabre1c-master/?CWD="+"/contacts/"+Объект.Код;
ПолеHTMLДокумента=Адрес;
КонецЕсли;
КонецПроцедуры

Готово.

Также можно написать простейшую обработку, чтобы выгрузить все файлы из хранилища в базе в папку на диске.

Процедура ЭкспортФайловХранилищаНажатие(Элемент)
Путь="d:wampwwwSabre1c-masterupload"
ИмяХранилищаДопИнф="ХранилищеДополнительнойИнформации";
Выборка = Справочники[ИмяХранилищаДопИнф].Выбрать();
Пока выборка.Следующий() = 1 Цикл
Попытка
// если у вас числовая нумерация, ID=Формат(выборка.Объект.Код,"ЧГ=0");
ID=выборка.Объект.Код;
Исключение
Попытка
// если у вас числовая нумерация, ID=Формат(выборка.Объект.Номер,"ЧГ=0");
ID=выборка.Объект.Номер;
Исключение
ID="null";
КонецПопытки;
КонецПопытки;

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

Всё нижеописанное Вы можете повторить для себя, но исключительно на свой страх и риск. Автор не несет ответственности за возникновение каких-либо проблем.

И удалить выгруженные файлы из БД.

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

Теперь, чтобы фактический размер БД уменьшился после удаления из нее хлама, осталось только выгрузить и загрузить ИБ.

5 Comments

  1. Prometeus2011

    Плюс за оригинальность и труды, но есть 2 замечания:

    1. Трудоемко. Требует использование стороннего ПО. Проще использовать зашитую в платформу 8.х возможность клиент-серверного обмена.

    2. Замена принципа работы интерфейса (в частности порядка прикрепления файлов к объектам) всегда переносится пользователями болезненно, особенно в организации, где пользюков, человек эдак 150 в базе сидит. По-этому, лучше внешне не менять ничего, а лишь при вызове штатных обработчиков перехватывать их исполнения и класть файлу не в ХЗ, а передавать на сервер. Но да это не столь важно.

    В общем, как вариант… Сам озабочен этим, ибо графики много, а хранить ее в базе — не кошерно.

    Reply
  2. Dimon2005

    Надо будет попробовать. Спасибо!!

    Reply
  3. zqzq

    Если у документа поменяют номер или у справочника код — все связанные файлы потеряются?.. Тогда уж к ссылке нужно привязываться.

    В БСП вроде что-то было для хранения файлов вне базы через веб-сервер.

    Reply
  4. dgolovanov

    Охренеть, простейший. Внедрите БСП и будет вам хранение файлов во внешних томах на дисках.

    Reply
  5. iolko
    Вы ощущаете когнитивный диссонанс, когда сталкиваетесь с многогигабайтной базой данных, забитой разношёрстными файлами хранилища дополнительной информации

    .

    Есть такой момент, НО. В 1С (практически все типовые конфигурации) этот механизм используют (если не настраивать хранение файлов на дисках).

    Здесь необходимо четкое понимание объемов хранения, и последствий, которые за собой эти хранимые объемы повлекут.

    У нас в компании уже много лет реализовано хранение прикрепленных файлов на дисках, а в базу пишется только путь до файла. При этом в данный момент объем хранимой информации, а это:

    screen shot-ы экранов пользователя с ошибками в отделе тех поддержки, различные заявки и пр, довольно велик, но собственно хранится и ни как не нагружает БД. При чем можно достаточно четко разграничить права доступа к этой информации средствами АД.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *