Интеграция 1С с внешними облачными сервисами — одна из наиболее частых задач в современной разработке. Довольно популярным сценарием является импорт данных из Google Таблиц, к которым предоставлен публичный доступ по ссылке. На первый взгляд задача кажется тривиальной: достаточно отправить простой HTTP-запрос. Однако на практике разработчики сталкиваются с тем, что вместо файла Excel (.xlsx) или CSV скачивается пустая HTML-страница со служебной информацией или ошибкой перенаправления.
В этой статье мы подробно разберем, почему возникает данная проблема, и по шагам реализуем надежный механизм скачивания публичных Google Таблиц из 1С без использования API-ключей и сложной OAuth-авторизации.
Когда мы пытаемся скачать документ по прямой ссылке в браузере, он автоматически обрабатывает все внутренние перенаправления. Но встроенный объект 1С HTTPСоединение по умолчанию не умеет следовать за редиректами (коды состояния 301, 302, 307, 308). Сервера Google при попытке скачать файл перенаправляют запрос со своего основного адреса на сервера доставки контента (например, поддомены *.googleusercontent.com).
В результате вместо скачивания файла 1С получает от сервера ответ с кодом 307 Temporary Redirect (или аналогичным) и HTML-страницей, содержащей текст "The document has moved here". Наша задача — научить 1С корректно считывать заголовок перенаправления Location и отправлять повторный запрос по новому адресу в автоматическом режиме.
Дополнительно Google часто блокирует запросы со стандартными или пустыми системными заголовками User-Agent, принимая их за вредоносных ботов. Чтобы избежать блокировки и появления капчи, нам потребуется имитировать запрос от имени реального браузера.
Рассмотрим правильный подход к организации HTTP-соединения. Вместо однократной проверки условия Если Ответ.КодСостояния = 307 мы реализуем цикл, который будет следовать по цепочке перенаправлений до тех пор, пока не получит успешный код ответа (200) или не достигнет лимита попыток (например, 5 итераций). Это защитит наш код от сбоев, если Google решит использовать множественный редирект.
Ниже представлен готовый программный код для скачивания файла:
Функция СкачатьПубличнуюТаблицуGoogle(Знач СсылкаНаТаблицу, ПутьДляСохранения) Экспорт
// Извлекаем идентификатор документа из ссылки
// Ссылка обычно имеет вид: https://docs.google.com/spreadsheets/d/[ИД_ДОКУМЕНТА]/edit...
ИДТаблицы = ПолучитьИДТаблицыИзСсылки(СсылкаНаТаблицу);
Если ПустаяСтрока(ИДТаблицы) Тогда
ВызватьИсключение "Не удалось определить идентификатор Google Таблицы!";
КонецЕсли;
// Формируем первоначальный адрес ресурса для экспорта в XLSX
// Используем современный параметр format вместо устаревшего exportFormat
АдресРесурса = "spreadsheets/d/" + ИДТаблицы + "/export?format=xlsx";
Хост = "docs.google.com";
Итерация = 1;
МаксимальноеКоличествоРедиректов = 5;
ФайлСкачан = Ложь;
Пока Итерация <= МаксимальноеКоличествоРедиректов Цикл
// Настраиваем защищенное SSL-соединение
Защита = Новый ЗащищенноеСоединениеOpenSSL;
Соединение = Новый HTTPСоединение(Хост, 443, , , , 15, Защита);
// Создаем запрос и обязательно подменяем User-Agent
Запрос = Новый HTTPЗапрос(АдресРесурса);
Запрос.Заголовки.Вставить("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
// Выполняем запрос
Ответ = Соединение.Получить(Запрос, ПутьДляСохранения);
КодCостояния = Ответ.КодСостояния;
// Проверяем успешность загрузки
Если КодCостояния = 200 Тогда
ФайлСкачан = Истина;
Прервать;
// Если встретили редирект (301, 302, 307, 308)
ИначеЕсли КодCостояния = 301 Или КодCостояния = 302 Или КодCостояния = 307 Или КодCостояния = 308 Тогда
// Считываем заголовок Location, куда нас перенаправляют
НовыйАдрес = Ответ.Заголовки.Получить("Location");
Если ПустаяСтрока(НовыйАдрес) Тогда
Прервать;
КонецЕсли;
// Парсим полученный URL на хост и путь к ресурсу
Если Найти(НовыйАдрес, "https://") > 0 Тогда
БезПротокола = СтрЗаменить(НовыйАдрес, "https://", "");
ИндексСлэша = Найти(БезПротокола, "/");
Если ИндексСлэша > 0 Тогда
Хост = Лев(БезПротокола, ИндексСлэша - 1);
АдресРесурса = Сред(БезПротокола, ИндексСлэша);
Иначе
Хост = БезПротокола;
АдресРесурса = "";
КонецЕсли;
Иначе
АдресРесурса = НовыйАдрес;
КонецЕсли;
Итерация = Итерация + 1;
Иначе
ВызватьИсключение "Не удалось скачать файл. Код ошибки сервера Google: " + КодCостояния;
КонецЕсли;
КонецЦикла;
Если Не ФайлСкачан Тогда
ВызватьИсключение "Превышено максимальное количество перенаправлений или произошла ошибка структуры ссылки!";
КонецЕсли;
Возврат Истина;
КонецФункции
Проанализируем вспомогательную функцию разбора ссылки, которая позволяет автоматически выделять уникальный идентификатор Google Таблицы:
Функция ПолучитьИДТаблицыИзСсылки(Знач Ссылка)
// Ищем стандартный маркер начала идентификатора
МаркерНачала = "/d/";
ПозицияНачала = Найти(Ссылка, МаркерНачала);
Если ПозицияНачала = 0 Тогда
Возврат "";
КонецЕсли;
СтрокаПослеМаркера = Сред(Ссылка, ПозицияНачала + СтрДлина(МаркерНачала));
// Идентификатор заканчивается следующим символом "/"
ПозицияКонца = Найти(СтрокаПослеМаркера, "/");
Если ПозицияКонца = 0 Тогда
Возврат СтрокаПослеМаркера;
КонецЕсли;
Возврат Лев(СтрокаПослеМаркера, ПозицияКонца - 1);
КонецФункции
По умолчанию приведенный выше алгоритм скачивает всю книгу Google Таблицы со всеми существующими вкладками в формате XLSX. Однако в практической работе часто требуется импортировать только конкретную вкладку или сразу загрузить данные в более легковесном формате CSV.
Для управления параметрами скачивания мы можем гибко модифицировать строку запроса, используя дополнительные параметры API Google Документов:
format=xlsx мы можем передать format=csv (для скачивания одного листа в текстовом формате с разделителями-запятыми) или format=pdf.gid. Его можно подсмотреть в адресной строке вашего браузера при переходе на нужный лист (например, #gid=13498572).Рассмотрим пример формирования пути запроса для скачивания конкретного листа в формате CSV:
// Пример скачивания листа с идентификатором 13498572 в формате CSV
АдресРесурса = "spreadsheets/d/" + ИДТаблицы + "/export?format=csv&gid=13498572";
При использовании формата CSV файл скачивается очень быстро, а его последующий разбор средствами 1С не требует распаковки тяжелых ZIP-архивов Office Open XML, из которых состоят файлы .xlsx. Для последующего чтения данных из сохраненных файлов подойдёт универсальная обработка для загрузки файлов Excel и CSV в 1С.
Если владелец исходной таблицы воспользовался функцией безопасности Файл -> Поделиться -> Опубликовать в интернете, то структура ссылок на скачивание меняется. Этот режим имеет ключевое преимущество: такие ссылки гораздо стабильнее отдают файлы скриптам и часто не требуют прохождения сложной цепочки редиректов.
Адрес опубликованного в сети документа содержит фрагмент вида /d/e/[ID_Публикации]/pubhtml. Для получения прямой ссылки на файл нам необходимо заменить окончание пути:
https://docs.google.com/spreadsheets/d/e/[ID_Публикации]/pub?output=xlsxhttps://docs.google.com/spreadsheets/d/e/[ID_Публикации]/pub?output=csvАлгоритм скачивания такого файла в 1С остается точно таким же, меняется только первоначальное заполнение переменной АдресРесурса.
Разберем еще один продвинутый метод, который редко упоминается на форумах, но крайне удобен для разработчиков 1С. Это использование интерфейса Google Visualization API (протокол источника данных Google Charts).
Этот способ позволяет скачивать данные публичных таблиц в формате CSV, обращаясь к листам напрямую по их текстовому названию (вместо неудобных числовых кодов gid), и даже отбирать конкретный диапазон ячеек прямо на стороне серверов Google.
Для реализации этого метода сформируем адрес запроса по следующему шаблону:
https://docs.google.com/spreadsheets/d/[ID_Таблицы]/gviz/tq?tqx=out:csv&sheet=[Имя_Листа]&range=A1:F500
Посмотрим на пример кода, подготавливающего такой запрос в 1С:
IDТаблицы = "1aBcDeFgHiJkLmNoPqRsTuVwXyZ"; // Замените на реальный ID таблицы
ИмяЛиста = "Выгрузка_1С"; // Имя вкладки на русском или английском языке
Диапазон = "A1:E100"; // Ограничиваем только нужной табличной частью
// Кодируем имя листа для безопасной передачи в URL
ИмяЛистаКодированное = КодироватьСтроку(ИмяЛиста, СпособКодированияСтроки.URLКодирование);
АдресРесурса = "spreadsheets/d/" + IDТаблицы + "/gviz/tq?tqx=out:csv"
+ "&sheet=" + ИмяЛистаКодированное
+ "&range=" + Диапазон;
// Передаем данный АдресРесурса в наш алгоритм с обработкой редиректов
Использование Visualization API существенно повышает гибкость интеграции, так как вам больше не нужно хранить в базе данных числовые gid вкладок, которые могут измениться при копировании или пересоздании листов пользователями. Текстовое имя листа намного понятнее и стабильнее в поддержке.
Применяя данные подходы, вы сможете выстроить отказоустойчивый и быстрый процесс синхронизации данных между Google Таблицами и вашей информационной базой на платформе 1С:Предприятие. Если же требуется двусторонний обмен или доступ к закрытым документам, можно использовать готовое решение для интеграции 1С с Google Таблицами через сервисный аккаунт.