gifts2017

Загрузка файла в БД, выгрузка и сохранение файла с БД

Опубликовал Сергей Галюк (dj_serega) в раздел Программирование - Практика программирования

С выходом новых релизов платформ 1С изменяются некоторые методы. Некоторые улучшаются, некоторые (не будем уточнять =) ). Тем не менее, изменения есть. В этой публикации я ознакомлю вас с методами загрузки и выгрузки файла (а это НачатьПомещениеФайла и НачатьПолучениеФайлов соответственно).

Разработано на 8.3.6.2041. Минимальная версия 8.3.3.641.

 

Для понимания механизма достаточно воспользоваться следующими новыми методами: НачатьПомещениеФайлаНачатьПолучениеКаталогаДокументовНачатьПолучениеФайлов. Вспомогательными будут: ОписаниеОповещенияФайлПолучитьИзВременногоХранилища.

В свойствах конфигурации установлено:

Режим использования модальности - Не использовать
Режим использования синхронных вызовов - Не использовать (Свойство доступно начиная с версии 8.3.6.1760)
Режим совместимости - Не использовать. 

Настройки БД:

Для реализации примера создал константу "Данные файла" (тип ХранилищеЗначения) общую форму "Сохранение файла". Через общую форму (где все реализовано) выполняется сохранение файла в константу, выгрузка и открытие загруженного ранее файла.

Спросите "Почему данные записываются в константу, а не в справочник или регистр сведений?". Тут все просто. Я посчитал что для упрощения понимания механизма использовать константу самое то :). Главное понять суть механизма, а вариант реализации программист уже выбирает исходя из структуры своей БД.

Почему не прикрепил конфигурацию, а выложил листинг кода?

Я считаю, что публикацию будет читать пользователь, уже имеющий опыт программирования в среде платформы 8.3 (умеет создавать объекты конфигурации, знает, что такое СП и как пользоваться встроенной справкой). Поэтому создать рабочий пример у себя в БД не составит особых проблем. Нужно: создать константу, создать общую форму, в новую форму вставить листинги кода (ниже в публикации), создать команды на форме (СохранитьФайл, ОткрытьФайл, УдалитьФайли подвязать обработчики.

Краткое описание используемых методов (копипаст СП не делал :) ):

НачатьПомещениеФайла - Вызывается диалог выбора файла. Выбранный файл помещается во временное хранилище. 
НачатьПолучениеФайлов - Выполняется получение данных файла с БД и сохранение файла в указанный пользователем каталог.
Файл - Доступ к свойствам файла по полному пути к файлу.
ПолучитьИзВременногоХранилища, ПоместитьВоВременноеХранилище - В данном примере это методы работы с двоичными данными файла.
НачатьПолучениеКаталогаДокументов (КаталогДокументов) - Получение каталога документов пользователя (аналог КаталогДокументов).
ОписаниеПередаваемогоФайла - Определение полного имени файла в ОС по которому будет сохранен файл из ИБ.
ОписаниеОповещения - Описание вызова процедуры которая будет вызвана после какого-то действия пользователя (Пример: После действия пользователя НачатьПолучениеКаталогаДокументов будет вызвана процедура, где в параметре "ИмяКаталогаДокументов" будет строка в полным адресом к каталогу документов пользоватя: "C:\Users\Имя пользователя\Documents"). 
НачатьЗапускПриложения - Открытие файла ассоциированным приложением. 

Примечание: Основные методы используются с 8.3.3.641. А НачатьПолучениеКаталогаДокументов с 8.3.6.1760.

Листинги:

Сохранение файла

#Область Сохранение_файла

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

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

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

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


#Область Открытие_файла

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

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

&НаКлиенте
Процедура ОткрытьФайлЗавершение(ПолученныеФайлы, ДополнительныеПараметры) Экспорт 
	
	Если ПолученныеФайлы = Неопределено
		И Не (ТипЗнч(ПолученныеФайлы) = Тип("Массив")
			И ПолученныеФайлы.Количество()) Тогда
		Возврат;
	КонецЕсли;
	
	НачатьЗапускПриложения(Новый ОписаниеОповещения("НачатьЗапускПриложенияЗавершение", ЭтотОбъект), ПолученныеФайлы[0].Имя);
	
КонецПроцедуры // ОткрытьФайлЗавершение

&НаКлиенте
Процедура НачатьЗапускПриложенияЗавершение(КодВозврата, ДополнительныеПараметры) Экспорт 
	
	// Заглушка
	
КонецПроцедуры // НачатьЗапускПриложенияЗавершение

&НаСервереБезКонтекста
Процедура ПолучитьДанныеФайлаНаСервереБезКонтекста(Адрес, ИмяФайла)  
	
	СтруктураФайла = Константы.ДанныеФайла.Получить().Получить();
	
	ИмяФайла = СтруктураФайла.ИмяФайла;
	
	ПоместитьВоВременноеХранилище(СтруктураФайла.ДанныеФайла, Адрес);
	
КонецПроцедуры // ПолучитьДанныеФайлаНаСервереБезКонтекста

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

Удаление файла

#Область Удаление_файла

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

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

&НаСервереБезКонтекста
Процедура УдалитьФайлНаСервереБезКонтекста()  
	
	Константы.ДанныеФайла.Установить(Неопределено);
	
КонецПроцедуры // УдалитьФайлНаСервереБезКонтекста

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

Служебная процедура (в которой выполняется проверка наличия данных константы) 

// Служебная процедура для проверки наличия загруженного файла
&НаСервереБезКонтекста
Функция   ПроверитьНаличиеФайлаВКонстантеНаСервереБезКонтекста()  
	
	ДанныеФайла = Константы.ДанныеФайла.Получить();
	
	Возврат Не ДанныеФайла.Получить() = Неопределено;
	
КонецФункции // ПроверитьНаличиеФайлаВКонстантеНаСервереБезКонтекста

P.S.: публикацию http://infostart.ru/public/396459/ видел. В ней немного другой подход к реализации подобной задачи.

 

теги: НачатьПомещениеФайла, НачатьПолучениеФайлов, ОписаниеПереданногоФайла

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Глафира Иванова (AlenkaInt) 22.01.16 14:54
Очень полезная обработка. Возьму себе.
2. Максим *** (premier) 23.01.16 12:35
(0) А релиз платформы 8.3 не указан. Или он не важен?
3. Сергей Галюк (dj_serega) 23.01.16 17:49
(2) premier, Если верить http://v8.1c.ru/o7/201301nm/ то "анти-модальность" появилась начиная с версии 8.3.3.641.
По асинхронности использовался метод "НачатьПолучениеКаталогаДокументов". Эти методы появились в 8.3.6.1760.

Реализация была на 8.3.7. (точную версию попозже напишу в публикации).
И наверно сделаю еще вариант без асинхронного метода.
4. Сергей Галюк (dj_serega) 25.01.16 09:54
(2) premier, Подкорректировал публикацию. Доработал процедуру "ОткрытьФайл".

&НаКлиенте
Процедура ОткрытьФайл(Команда)
    
    Если ПроверитьНаличиеФайлаВКонстантеНаСервереБезКонтекста() Тогда
        
        // Начиная с версии 8.3.6.1760 (отказ от асинхронных методов)
        НачатьПолучениеКаталогаДокументов(Новый ОписаниеОповещения("КаталогДокументовЗавершение", ЭтотОбъект));
        // До 8.3.6.1760
        //КаталогДокументов = КаталогДокументов();
        //КаталогДокументовЗавершение(КаталогДокументов, "");
        
    Иначе
        
        СообщениеПользователю = Новый СообщениеПользователю;
        СообщениеПользователю.Текст = "Файл не был загружен в константу.";
        СообщениеПользователю.Сообщить();
        
    КонецЕсли;
    
КонецПроцедуры
...Показать Скрыть
5. Caponid V (caponid) 25.01.16 11:19
И что будет с константой когда много пользователей будут сохранять/получать разные файлы?
6. Сергей Галюк (dj_serega) 25.01.16 11:23
(5) caponid, Так я для примера ж сделал :) В реальной жизни у меня в справочник пишется.
Главное же понять механизм а реализация для каждого своя :)
7. Caponid V (caponid) 25.01.16 12:34
Так для примера это и есть плохо)) Пример не должен содержать потенциальных ошибок - либо обговаривать что эту часть реализации надо для себя разрабатывать самому, потому что пример в многопользовательском режиме может выдать плавающую ошибку (по получению некорректных данных).
8. Сергей Галюк (dj_serega) 25.01.16 12:37
(7) caponid, Спасибо. Я понял. Что бы понятней было придется конфу приложить?
9. Caponid V (caponid) 25.01.16 12:47
(8) dj_serega, конфигурация это лишнее), просто в тексте статьи указать опасность использования константы ;-)
dj_serega; +1 Ответить
10. Alexander F (lx@) 06.02.16 07:45
Не понял зачем нужна НачатьПолучениеКаталогаДокументов(), КаталогДокументов - это же не модальная функция?
11. Сергей Галюк (dj_serega) 06.02.16 22:44
(10) lx@, Источник
Реализована поддержка асинхронной работы с криптографией, внешними компонентами и расширенной работы с файлами в веб-клиенте, обеспечивающая возможность работы с веб-браузером Google Chrome.
Необходимо помнить, что поддержку синхронных вызовов в веб-браузере Google Chrome планируется прекратить 1 апреля 2015 года. При этом синхронные методы во встроенном языке также перестанут работать, несмотря на то, что сама платформа поддерживает эти вызовы.


Почему переписал? Потому что оно ругалось на платформе разработки. Проверки всегда стоят: ТонкийКлиент, ВебКлиент, ТолстыйКлиентУправляемоеПриложение, Сервер. Вообщем все галочки.
12. Vasiliy Serpenskiy (forestrg) 24.11.16 09:45
а как &НаСервереБезКонтекста обратится к реквизиту справочника? или реквизиту ТЧ.
PS Я начинающий и прошу сильно не пинать
13. Vasiliy Serpenskiy (forestrg) 24.11.16 16:34
в частности как изменить этот кусок
 СтруктураФайла = Константы.ДанныеФайла.Получить().Получить();