Довольно часто возникает задача предоставить сторонним пользователям или внешним системам возможность быстро скачать файл из 1С по прямой ссылке. Нередко разработчики пытаются использовать для этого уже существующий Web-сервис (SOAP), надеясь просто дописать нужный идентификатор в адресную строку браузера. Выясним, почему такой подход не сработает со стандартными Web-сервисами, и разберем правильный способ реализации отдачи файлов средствами 1С.
Проанализируем технические особенности работы стандартных Web-сервисов в платформе 1С. Они базируются на протоколе SOAP, который жестко регламентирует правила взаимодействия:
SOAPAction для SOAP 1.1 или соответствующий Content-Type)..../base/ws/DocWork.1cws?wsdl отдает только XML-описание схемы сервиса (WSDL), а передать туда параметры функции через ?param=value невозможно.Попытка вызвать метод SOAP напрямую из браузера потребует либо написания клиентского скрипта на JavaScript с формированием XML и настройкой CORS, либо создания промежуточного веб-сервера. Однако в платформе 1С есть гораздо более простое и нативное решение — использование объекта конфигурации HTTP-сервис.
Разберем по шагам, как переделать отдачу файла на HTTP-сервис, чтобы браузер мог обращаться к нему простым GET-запросом и сразу скачивать сформированный файл.
В дереве метаданных конфигурации перейдем в ветку Общие — HTTP-сервисы и создадим новый сервис, например, с именем DocWork. В свойствах укажем корневой URL (например, DocWork).
Параметры из браузера можно передать двумя способами:
.../hs/DocWork?ID_kod=123./{ID_kod}, тогда ссылка для пользователя примет вид .../hs/DocWork/123.Создадим для шаблона метод с типом HTTP-метода GET и перейдем в модуль сервиса. Рассмотрим пример реализации функции-обработчика, которая считывает переданный идентификатор, получает двоичные данные файла и возвращает правильный HTTP-ответ:
Функция DocWorkОбработкаGET(Запрос)
// Способ 1: Получение параметра из строки запроса (?ID_kod=...)
ЗначениеИД = Запрос.ПараметрыЗапроса.Получить("ID_kod");
// Способ 2 (если используется шаблон вида /{ID_kod}):
// ЗначениеИД = Запрос.ПараметрыURL.Получить("ID_kod");
Если Не ЗначениеЗаполнено(ЗначениеИД) Тогда
// Возвращаем ошибку 400 Bad Request, если обязательный параметр не указан
Возврат Новый HTTPСервисОтвет(400);
КонецЕсли;
// Получаем двоичные данные файла (например, из хранилища значений или формируем на лету)
// ДвоичныеДанныеФайла = ПолучитьФайлПоИдентификатору(ЗначениеИД);
Если ДвоичныеДанныеФайла = Неопределено Тогда
// Возвращаем ошибку 404 Not Found, если объект не найден
Возврат Новый HTTPСервисОтвет(404);
КонецЕсли;
// Формируем успешный ответ для браузера
Ответ = Новый HTTPСервисОтвет(200);
// Задаем тип содержимого
Ответ.Заголовки.Вставить("Content-Type", "application/octet-stream");
// Указываем браузеру, что файл нужно скачать, а не отображать в окне
ИмяФайла = "document_" + ЗначениеИД + ".pdf";
Ответ.Заголовки.Вставить("Content-Disposition", "attachment; filename=""" + ИмяФайла + """");
// Заполняем тело ответа бинарными данными
Ответ.УстановитьТелоИзДвоичныхДанных(ДвоичныеДанныеФайла);
Возврат Ответ;
КонецФункции
Рассмотрим дополнительные моменты, с которыми придется столкнуться при обращении к сервису из браузера:
attachment; filename="...". Без нее браузер может попытаться открыть файл внутри вкладки как простой текст или сообщить о поврежденном содержимом.http://user:password@server/... нельзя, так как современные браузеры блокируют такие URL в целях безопасности.default.vrd в параметрах строки подключения базы можно явно указать специального служебного пользователя с минимальными правами (параметры usr=...;pwd=...;).Если нет возможности дорабатывать конфигурацию и создавать новый HTTP-сервис, проанализируем еще одну стандартную возможность платформы. Если файл уже хранится в типовом справочнике или регистре в реквизите с типом ХранилищеЗначения, и в базе включен стандартный интерфейс OData, то скачать двоичные данные можно стандартным GET-запросом прямо из адресной строки браузера без написания программного кода:
Для этого используется суффикс /$value в конце адреса нужного реквизита, например:
http://сервер/база/odata/standard.odata/Справочник_Файлы(guid'00000000-0000-0000-0000-000000000000')/ХранилищеФайла/$value
При таком запросе платформа 1С автоматически сформирует бинарный поток и отдаст файл клиенту.