Реализация скачивания печатной формы документа через веб-сайт с использованием HTTP-сервиса

Публикация № 1103082

Программирование - Практика программирования

62
В статье показан пример, как реализовать скачивание печатной формы документа клиентом (пользователем) по ссылке на веб-сайте.

Наткнулся на публикацию Табличный документ через HTTP сервис и решил поделиться своим опытом.

У организации есть сайт, на этом сайте у клиентов есть личный кабинет. В нём отображаются данные из 1С об их заказах. Необходимо было добавить ссылку (URL), нажав на которую пользователь смог бы скачать печатную форму своих заказов в формате PDF. Для опытного разработчика 1С, в принципе, задача не представляет особой сложности, но, может, эта статья поможет начинающим программистам или тем, кто только осваивает HTTP-сервисы.

Итак, приступим к реализации. В качестве примера будем использовать конфигурацию "Управление торговлей 11" и возвращать печатную форму документа "Заказ клиента".

Нам необходим HTTP-сервис, который отдаст клиенту печатную форму документа. Назовём этот сервис, например, ПередачаДокументов, в качестве корневого URL используем значение GetDocuments. Также потребуется шаблон URL, назовём его Download. Входящим параметром будет являться уникальный идентификатор документа, печатную форму которого необходимо получить. Итоговый URL для скачивания будет иметь следующий вид: http://<адрес_базы_1с>/hs/GetDocuments/Download/<УникальныйИдентификатор>.

Создадим HTTP-сервис:

Добавим шаблон URL:

В созданный шаблон добавим HTTP-метод GET:

И реализуем обработчик этого метода:

Функция ПолучитьПечатнуюФормуGET(Запрос)
	
	Попытка
		// Получим переданный в HTTP-запросе идентификатор документа.
		Идентификатор = Новый УникальныйИдентификатор(Запрос.ПараметрыURL["Идентификатор"]);
	Исключение
		// Полученный параметр не смогли преобразовать в тип "УникальныйИдентификатор".
		HTTPОтвет = Новый HTTPСервисОтвет(400); // 400 - Bad Request
		HTTPОтвет.УстановитьТелоИзСтроки(НСтр("ru='Передан неверный идентификатор'"));
		Возврат HTTPОтвет;
	КонецПопытки; 
	
	// Найдём документ по полученному идентификатору.
	ДокументСсылка = Документы.ЗаказКлиента.ПолучитьСсылку(Идентификатор);
	
	Если ДокументСсылка.ПолучитьОбъект() = Неопределено Тогда
		// Документ с таким уникальным идентификатором не существует.
		HTTPОтвет = Новый HTTPСервисОтвет(404); // 404 - Not Found
		HTTPОтвет.УстановитьТелоИзСтроки(НСтр("ru='Документ не найден'"));
		Возврат HTTPОтвет;
	КонецЕсли; 
	
	#Область ФормированиеПечатнойФормыДокумента
	
	МассивОбъектов = Новый Массив;
	МассивОбъектов.Добавить(ДокументСсылка);
	
	СтруктураТипов = ОбщегоНазначенияУТ.СоответствиеМассивовПоТипамОбъектов(МассивОбъектов);
	ОбъектыПечати = Новый Структура;
	ПараметрыПечати = Неопределено;
	
	// Вызов типовой процедуры печати документа.
	ТабличныйДокумент = Обработки.ПечатьЗаказовНаТоварыУслуги.СформироватьПечатнуюФормуЗаказаКлиента(
		СтруктураТипов, ОбъектыПечати, ПараметрыПечати);
		
	// Запишем табличный документ в поток в памяти в формате PDF.
	Поток = Новый ПотокВПамяти;
	ТабличныйДокумент.Записать(Поток, ТипФайлаТабличногоДокумента.PDF);
	
	// Получим двоичные данные для отправки клиенту
	ДвоичныеДанные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
	
	#КонецОбласти 
	
	#Область ОтправкаОтветаКлиенту
	
	// Сформируем имя файла, с которым печатная форма будет загружена у клиента.
	ИмяФайла = Строка(ДокументСсылка) + ".pdf";
	// Кодируем строку URL, чтобы избежать проблем с русскими буквами и другими символами (например, пробел).
	ИмяФайла = КодироватьСтроку(ИмяФайла, СпособКодированияСтроки.КодировкаURL);
	
	// Создадим ответ.
	HTTPОтвет = Новый HTTPСервисОтвет(200); // 200 - OK
	
	// Установим заголовки.
	HTTPОтвет.Заголовки.Вставить("Content-Type", "application/pdf"); // Чтобы браузер знал, что это PDF
	HTTPОтвет.Заголовки.Вставить("Content-Disposition", "attachment; filename=""" + ИмяФайла + """");
	
	// Телом ответа являются двоичные данные печатной формы.
	HTTPОтвет.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанные);
	
	// И, наконец, вернём ответ клиенту.
	Возврат HTTPОтвет;
		
	#КонецОбласти 
	
КонецФункции

В коде постарался максимально доступно описать выполняемые действия комментариями. Резюмируем, что делает данный обработчик:

  • производится поиск документа по переданному уникальному идентификатору;
  • вызывается стандартная процедура печати документа (аналогично тому, как если бы пользователь нажал кнопку "Печать" в 1С), результатом является табличный документ;
  • табличный документ записывается в нужном формате (при этом используется поток в памяти, чтобы избежать операций с временными файлами);
  • формируется ответ.

Таким образом, когда клиент в личном кабинете нажимает на ссылку для скачивания печатной формы, его браузер производит загрузку файла из 1С. В каталоге загрузок у клиента появится файл вида "Заказ клиента №00001 от 03.08.2019.pdf".

62

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. Поручик 4294 04.08.19 23:47 Сейчас в теме
Мне тоже поможет. С HTTP-сервисами ещё не работал
2. dsdred 1129 05.08.19 07:41 Сейчас в теме
Меня только одно смущает, почему УникальныйИдентификатор не "Параметром Запроса" оформлен?

http://host/base/hs/корневойURL/относительныйURL?ПараметрыЗапроса

Шаблон был бы: /Download

Запрос: http://<адрес_базы_1с>/hs/GetDocuments/Download?UUID=<УникальныйИдентификатор>

А так пример неплохой.

А по хорошему так:
Шаблон был бы: /Download/{ТипДокумента}

Запрос: http://<адрес_базы_1с>/hs/GetDocuments/Download/<ТипДокумента>?UUID=<УникальныйИдентификатор>

Тут подробнее: https://infostart.ru/public/842751/
3. trntv 23 05.08.19 09:03 Сейчас в теме
(2) Почему смущает? Спрашиваю, потому что я бы сделал также. Ну разве что шаблон "Download" слишком обобщающий, но в качестве примера допустим.
4. dsdred 1129 05.08.19 09:17 Сейчас в теме
(3)Потому, что используется метод Get, и в таком виде метод получается не гибкий.
Через параметры можно передавать что угодно Уникальный идентификатор, номер, дату и т.д.

Шаблон: /Download/{ТипДокумента}

Вот что получим:

Поиск по УИ:
Запрос: http://<адрес_базы_1с>/hs/GetDocuments/Download/ЗаказКлиента?UUID=<УникальныйИдентификатор>

Поиск по Коду + Номер
http://<адрес_базы_1с>/hs/GetDocuments/Download/ЗаказКлиента?Number=00000022&Date=22.12.2018

и т.д.

Получается более универсальное решение выйдет, а то что предложено в статье это как бетоном залить насмерть. Да и Download тоже согласен что лишнее тут...

П.С. Я за универсальность решений.
5. androgin 05.08.19 15:18 Сейчас в теме
я вот вообще не сторонник передавать параметры в строке. Уж лучше в тело запроса упаковывать все. Безопаснее
6. dsdred 1129 05.08.19 20:40 Сейчас в теме
(5)Забавно но безопаснее не совсем подходит под описание методов типа Post и подобным методам ;)

Безопасные — это методы, которые могут лишь запросить информацию. Они не могут изменить запрашиваемый ресурс, не могут привести к нежелательным результатам для пользователя, других лиц или сервера.

А вообще, да Post и похожие методы не кешируются в браузере и являются более конфиденциальными.
Вот по сравнению методов писал как то: https://infostart.ru/public/886103/

Картинка ниже, утрировано, но очень наглядно показывает выбор между GET и POST:
7. androgin 06.08.19 15:12 Сейчас в теме
(6) передавать длинные параметры в строке - это ужасно)))))
8. dsdred 1129 06.08.19 15:17 Сейчас в теме
(7)Никто не заставляет передавать длинные параметры. ;)
Просто надо понимать для чего сервис и какой метод под него нужен.
Оставьте свое сообщение