Загрузка файла из интернета в 1С:Предприятие 8.3 через HTTPСоединение и БСП
Содержание
Чтобы скачать файл по ссылке в 1С, разберите адрес на сервер и путь, создайте HTTPСоединение, отправьте HTTPЗапрос методом Получить(Запрос, ИмяВыходногоФайла) и проверьте КодСостояния ответа. Если код 200, файл уже лежит на диске. В типовых конфигурациях на БСП то же самое делает одна строка: ПолучениеФайловИзИнтернета.СкачатьФайлНаСервере(URL).
Обычно задача звучит так: поставщик прислал ссылку на прайс, банк отдаёт выписку по адресу, сервис возвращает PDF. Нужно забрать файл в базу без ручного «сохранить как». Ниже рабочий код для платформы 8.3, разбор HTTPS и перенаправлений, приёмы для больших файлов и ошибки, которые встречаются чаще других.
Что подготовить до написания кода
Сначала решите, где будет выполняться загрузка. От этого зависят сеть, права и способ отдать файл пользователю.
| Где выполняется | Когда подходит | На что смотреть |
|---|---|---|
| 🖥️ На сервере 1С | Регламентные задания, обмены, клиент-серверная база | Сеть и прокси у учётной записи службы сервера 1С, а не у пользователя |
| 💻 На клиенте (тонкий, толстый) | Файл нужен только этому пользователю | В веб-клиенте HTTPСоединение недоступно |
| 📁 Файловая база | Небольшая организация | Код «на сервере» фактически выполняется на компьютере пользователя |
Для серверного варианта проверьте, что с машины, где работает служба 1С, адрес открывается. Служба обычно запущена от отдельного пользователя (часто USR1CV8). У него может не быть прокси-настроек, которые прописаны в браузере администратора. Самая частая загадка «у меня в браузере качается, а из 1С нет» объясняется именно этим.
Ещё три вещи до старта:
- 🔗 Ссылка прямая. Ссылка на страницу «скачать» у облачных дисков отдаёт HTML, а не файл. Нужна ссылка, по которой браузер сразу начинает загрузку.
- 🔐 Авторизация. Если ресурс требует логин, заранее узнайте её вид: базовая (логин и пароль), токен в заголовке или cookie после входа.
- 📦 Размер. Для файлов от сотни мегабайт сразу планируйте запись на диск, а не в память.
Как платформа работает с HTTP: соединение, запрос, ответ
Загрузка собирается из трёх объектов встроенного языка.
HTTPСоединение— соединение с одним сервером. Конструктор принимает хост, порт, пользователя, пароль, прокси, таймаут в секундах и объект защищённого соединения. Путь к файлу сюда не передают, только адрес сервера.HTTPЗапрос— путь на сервере вместе со строкой параметров (/files/price.xlsx?id=15) и соответствие заголовков.HTTPОтвет— результат. Из него берутКодСостояния,Заголовкии тело.
У метода Получить два режима. Без второго параметра тело ответа остаётся в памяти, его забирают через ПолучитьТелоКакДвоичныеДанные(). Со вторым параметром ИмяВыходногоФайла платформа сама пишет тело в файл по мере получения.
Для HTTPS нужен объект ЗащищенноеСоединениеOpenSSL. Если создать его без параметров, соединение шифруется, но сертификат сервера не проверяется. Правильнее передать хранилище корневых сертификатов: Новый СертификатыУдостоверяющихЦентровОС в актуальных версиях платформы или Новый СертификатыУдостоверяющихЦентровWindows на серверах под Windows.
Порт можно не указывать: при наличии защищённого соединения платформа подставит 443, без него 80. Явный порт нужен, только если он нестандартный и записан в адресе после двоеточия.
Пошаговая инструкция: скачиваем файл по ссылке кодом
Код ниже работает в любой конфигурации, БСП не нужна. Поместите его в общий модуль с флажком «Сервер» (например, ЗагрузкаФайлов), тогда директивы компиляции не понадобятся.
Шаг 1. Разобрать URL на части
Функция РазобратьURL(Знач URL) Экспорт
Результат = Новый Структура("Схема, Хост, Порт, Путь", "http", "", 0, "/");
Позиция = СтрНайти(URL, "://");
Если Позиция > 0 Тогда
Результат.Схема = НРег(Лев(URL, Позиция - 1));
URL = Сред(URL, Позиция + 3);
КонецЕсли;
Позиция = СтрНайти(URL, "/");
Если Позиция > 0 Тогда
ХостПорт = Лев(URL, Позиция - 1);
Результат.Путь = Сред(URL, Позиция);
Иначе
ХостПорт = URL;
КонецЕсли;
Позиция = СтрНайти(ХостПорт, ":");
Если Позиция > 0 Тогда
Результат.Хост = Лев(ХостПорт, Позиция - 1);
Результат.Порт = Число(Сред(ХостПорт, Позиция + 1));
Иначе
Результат.Хост = ХостПорт;
Результат.Порт = ?(Результат.Схема = "https", 443, 80);
КонецЕсли;
Возврат Результат;
КонецФункции
Для адреса https://example.ru/upload/price.xlsx?v=2 получится схема https, хост example.ru, порт 443 и путь /upload/price.xlsx?v=2. В типовых конфигурациях вместо своей функции можно взять ОбщегоНазначенияКлиентСервер.СтруктураURI(URL).
Шаг 2. Найти заголовок без учёта регистра
Сервер может прислать Location, а может location. Соответствие в 1С чувствительно к регистру ключа, поэтому ищем перебором:
Функция ЗначениеЗаголовка(Ответ, Имя)
Для Каждого КлючИЗначение Из Ответ.Заголовки Цикл
Если НРег(КлючИЗначение.Ключ) = НРег(Имя) Тогда
Возврат КлючИЗначение.Значение;
КонецЕсли;
КонецЦикла;
Возврат "";
КонецФункции
Шаг 3. Скачать файл с учётом перенаправлений
HTTPСоединение не переходит по редиректам само. Ответ 301 или 302 придёт как есть, а в файле окажется пустая или служебная страница. Поэтому перенаправления обрабатываем вручную, с ограничением на пять переходов:
Функция СкачатьФайлПоСсылке(Знач URL, Знач Расширение = "") Экспорт
ИмяФайла = ПолучитьИмяВременногоФайла(Расширение);
КодыПеренаправления = СтрРазделить("301,302,303,307,308", ",");
Для НомерПерехода = 1 По 5 Цикл
Части = РазобратьURL(URL);
Защищенное = Неопределено;
Если Части.Схема = "https" Тогда
Защищенное = Новый ЗащищенноеСоединениеOpenSSL(, Новый СертификатыУдостоверяющихЦентровОС);
КонецЕсли;
Соединение = Новый HTTPСоединение(Части.Хост, Части.Порт, , , , 60, Защищенное);
Заголовки = Новый Соответствие;
Заголовки.Вставить("User-Agent", "1C-Enterprise");
Запрос = Новый HTTPЗапрос(Части.Путь, Заголовки);
Ответ = Соединение.Получить(Запрос, ИмяФайла);
Код = Формат(Ответ.КодСостояния, "ЧГ=0");
Если Ответ.КодСостояния = 200 Тогда
Возврат ИмяФайла;
ИначеЕсли КодыПеренаправления.Найти(Код) <> Неопределено Тогда
НовыйАдрес = ЗначениеЗаголовка(Ответ, "Location");
Если ПустаяСтрока(НовыйАдрес) Тогда
Прервать;
КонецЕсли;
Если Лев(НовыйАдрес, 1) = "/" Тогда
НовыйАдрес = Части.Схема + "://" + Части.Хост + ":"
+ Формат(Части.Порт, "ЧГ=0") + НовыйАдрес;
КонецЕсли;
URL = НовыйАдрес;
Иначе
УдалитьФайлы(ИмяФайла);
ВызватьИсключение "Сервер вернул код " + Код + " по адресу " + URL;
КонецЕсли;
КонецЦикла;
УдалитьФайлы(ИмяФайла);
ВызватьИсключение "Не удалось скачать файл: перенаправления не привели к файлу";
КонецФункции
Функция возвращает полный путь к временному файлу на сервере. Удалить его после использования — забота вызывающего кода.
Шаг 4. Отдать файл пользователю
Пользователю файл с сервера передают через временное хранилище. В модуле формы:
&НаСервере
Функция АдресСкачанногоФайла(Знач URL)
ИмяФайла = ЗагрузкаФайлов.СкачатьФайлПоСсылке(URL, "pdf");
Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяФайла), УникальныйИдентификатор);
УдалитьФайлы(ИмяФайла);
Возврат Адрес;
КонецФункции
&НаКлиенте
Процедура СкачатьПоСсылке(Команда)
Адрес = АдресСкачанногоФайла(СсылкаНаФайл);
ФайловаяСистемаКлиент.СохранитьФайл(Неопределено, Адрес, "document.pdf");
КонецПроцедуры
Здесь СсылкаНаФайл — реквизит формы со строкой адреса. ФайловаяСистемаКлиент есть в конфигурациях на БСП. Без БСП используйте платформенный НачатьПолучениеФайлаССервера (платформа 8.3.18 и выше).
Скачивание файлов в типовой конфигурации на БСП
В Бухгалтерии 3.0, ЗУП 3.1, УТ 11 и других конфигурациях на БСП свой HTTP-код писать не обязательно. Подсистема «Получение файлов из интернета» уже умеет редиректы, прокси из настроек программы и защищённое соединение.
ПараметрыПолучения = ПолучениеФайловИзИнтернетаКлиентСервер.ПараметрыПолученияФайла();
ПараметрыПолучения.Таймаут = 60;
Результат = ПолучениеФайловИзИнтернета.СкачатьФайлНаСервере(URL, ПараметрыПолучения);
Если Не Результат.Статус Тогда
ВызватьИсключение Результат.СообщениеОбОшибке;
КонецЕсли;
ИмяФайла = Результат.Путь;
В параметрах получения также задают заголовки, логин и пароль, путь для сохранения. Состав полей смотрите прямо в функции ПараметрыПолученияФайла в конфигураторе: он меняется от версии БСП.
Если файл нужно прикрепить к документу или справочнику, кладите его в подсистему «Работа с файлами», а не храните путь к временному файлу. Скачанный файл помещают во временное хранилище и передают в РаботаСФайлами.ДобавитьФайл вместе со структурой из РаботаСФайлами.ПараметрыДобавленияФайла(). В ней указывают владельца (ссылку на объект), имя без расширения и расширение. Файл появится в списке присоединённых файлов объекта, как если бы его перетащили мышью.
Не вносите эти функции в модули типовой конфигурации напрямую. Пишите их во внешней обработке или в расширении конфигурации, иначе при следующем обновлении придётся сравнивать и объединять изменения вручную.
Большие файлы: пишем сразу на диск
Для архивов, выгрузок и видео главное правило одно: не держать тело ответа в памяти. Вариант Ответ.ПолучитьТелоКакДвоичныеДанные() грузит весь файл в оперативную память рабочего процесса. На файле в 1–2 ГБ это заканчивается ошибкой нехватки памяти или заметным торможением сервера у всех пользователей.
Что делать:
- Передавайте в
Получитьвторой параметр с именем файла, как в коде выше. Платформа пишет данные на диск частями. - Увеличьте таймаут. 60 секунд хватает для прайса, но не для архива на 800 МБ по медленному каналу. Ставьте 300–600 секунд или считайте от ожидаемой скорости.
- Узнайте размер заранее. Метод
Соединение.ПолучитьЗаголовки(Запрос)отправляет запрос HEAD и возвращает только заголовки. ЗначениеContent-Lengthподскажет, хватит ли места и стоит ли вообще качать. - Не гоняйте гигабайты через временное хранилище к клиенту. Если файл нужен для обработки на сервере, обработайте его там же и отдайте пользователю результат.
ОтветЗаголовки = Соединение.ПолучитьЗаголовки(Запрос);
ДлинаСтрокой = ЗначениеЗаголовка(ОтветЗаголовки, "Content-Length");
Если ЗначениеЗаполнено(ДлинаСтрокой)
И Число(ДлинаСтрокой) > 200 * 1024 * 1024 Тогда
ВызватьИсключение "Файл больше 200 МБ, загрузка отменена";
КонецЕсли;
Не все серверы присылают Content-Length, особенно при динамической отдаче. Поэтому после загрузки дополнительно проверьте фактический размер: Новый Файл(ИмяФайла).Размер().
Регламентное задание, которое качает большие файлы, ставьте на ночное время: загрузка нагружает сеть и диск сервера и может замедлить работу пользователей.
Безопасность и проверка скачанного файла
Код 200 ещё не значит, что пришёл нужный файл. Сервер мог вернуть страницу входа, сообщение «файл не найден» в HTML или обрезанный архив. Перед тем как разбирать файл, проверьте его.
- 🧾 Тип содержимого. Заголовок
Content-Typeдля HTML-страницы будетtext/html. Для PDF ждитеapplication/pdf, для XLSX — тип сspreadsheetml. - 🔢 Первые байты. PDF начинается с символов
%PDF(байты 37, 80, 68, 70). Файлы XLSX, DOCX и ZIP начинаются сPK(байты 80, 75). - 📏 Размер. Пустой файл или файл в пару килобайт вместо ожидаемых мегабайт — повод остановиться.
- #️⃣ Контрольная сумма. Если поставщик публикует хеш, сверьте его через
ХешированиеДанныхсХешФункция.SHA256.
Проверка сигнатуры PDF:
Функция ЭтоPDF(ИмяФайла)
Чтение = Новый ЧтениеДанных(ИмяФайла);
Сигнатура = Новый Массив;
Для Сч = 1 По 4 Цикл
Сигнатура.Добавить(Чтение.ПрочитатьБайт());
КонецЦикла;
Чтение.Закрыть();
Возврат Сигнатура[0] = 37 И Сигнатура[1] = 80
И Сигнатура[2] = 68 И Сигнатура[3] = 70;
КонецФункции
Отдельно про адреса, которые вводит пользователь. Если в форме есть поле «ссылка», через него можно заставить сервер 1С обращаться к внутренним ресурсам сети: http://192.168.1.10/..., консолям администрирования и т.п. Защита простая:
- держите список разрешённых доменов и сверяйте с ним хост после разбора URL;
- допускайте только схемы
httpиhttps; - не запускайте скачанные
.exe,.bat,.jsи не открывайте их программно; - логин и пароль к ресурсу храните в безопасном хранилище БСП (
ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище), а не в тексте модуля.
Внешняя обработка, подключённая в безопасном режиме, не получит доступ к интернету без разрешения. В типовых конфигурациях с включёнными профилями безопасности программа сама запросит разрешение на интернет-ресурс при регистрации обработки.
Ошибки при загрузке файла по ссылке и как их снять
Платформа передаёт текст ошибки сетевой библиотеки, поэтому сообщения часто на английском и начинаются со слов Ошибка работы с Интернет:. Выберите свой случай:
Если код упорно не работает на сервере, а в браузере на той же машине файл качается, проверьте прокси-настройки именно пользователя, от которого запущена служба 1С. Временно для диагностики можно выполнить тот же код в файловой базе или на клиенте: если там загрузка проходит, дело в сетевом окружении службы, а не в коде.
Частые вопросы
Можно ли скачать файл по ссылке без программирования?
ПерейтиПоНавигационнойСсылке.Почему в веб-клиенте код не работает?
HTTPСоединение недоступен. Выполняйте загрузку на сервере и передавайте пользователю результат через временное хранилище.Как скачать файл, если нужен POST-запрос?
HTTPЗапрос, задайте тело методом УстановитьТелоИзСтроки и вызовите Соединение.ОтправитьДляОбработки(Запрос, ИмяВыходногоФайла). Второй параметр так же пишет ответ в файл.Где лежит временный файл на сервере?
ПолучитьИмяВременногоФайла создаёт имя в каталоге временных файлов пользователя, от которого работает процесс сервера 1С. Удаляйте файл сразу после обработки, иначе каталог быстро разрастается.