Яндекс.Диск¶
YandexDiskStrategy — провайдер для Яндекс.Диска. Структурно повторяет Google Drive стратегию, но проще: REST API напрямую через httpx, без специфичных SDK. Файлы адресуются путями, а не ID — это меняет поведение в нескольких местах.
Когда выбирать¶
- Российская компания, нужно хранение на территории РФ.
- Уже есть подписка Яндекс 360.
- Не нужны Shared Drives как у Google — обычно достаточно одной шары на пользователя.
API¶
Базовый URL — https://cloud-api.yandex.net/v1/disk. Документация Яндекса.
Все вызовы — обычные REST через httpx.AsyncClient. Не нужна синхронная обёртка как у Google (googleapiclient).
Авторизация — OAuth2¶
Стратегия хранит в AttachmentStorage:
yandex_client_id / yandex_client_secret Char
OAuth client из oauth.yandex.ru.
yandex_access_token / yandex_refresh_token Text
Текущий и рефреш токены. Как у Google — access живёт ~1 час, refresh не протухает.
Поток OAuth¶
Структурно идентичен Google — пользователь идёт на oauth.yandex.ru, авторизуется, возвращается с code, бэк меняет код на пару токенов. Особенность только в эндпоинтах:
Автообновление¶
get_credentials() проверяет, не пора ли обновлять access_token (если осталось < 5 мин). Если да — POST на /token с grant_type=refresh_token. Полученный новый access_token (и иногда новый refresh_token) сохраняется в AttachmentStorage.
Адресация файлов — путь, а не ID¶
В отличие от Google Drive, где у каждого файла стабильный ID, в Яндекс.Диске файл идентифицируется путём:
Это значит:
- При переименовании папки или файла "ID" фактически меняется.
Attachment.storage_file_idиstorage_file_urlхранят путь, не идентификатор.- При синхронизации FARA должна следить, чтобы пути совпадали —
enable_routes_cronпоможет переименовать папки, если изменилсяnameзаписи.
Особенность: follow_redirects¶
Это ключевой нюанс при работе с Яндекс.Диском, который легко упустить.
Запросы на скачивание (/v1/disk/resources/download) и заливку (/v1/disk/resources/upload) возвращают 302 редирект на CDN-хост, а не сам файл/URL для аплоада. По умолчанию httpx.AsyncClient не следует редиректам (в отличие от requests).
# ❌ Неверно — вернёт 302, не дойдёт до файла
async with httpx.AsyncClient() as client:
response = await client.get(download_url)
# ✅ Правильно — следуем редиректу до CDN
async with httpx.AsyncClient(
timeout=HTTP_TIMEOUT,
follow_redirects=True,
) as client:
response = await client.get(download_url)
Стратегия везде ставит follow_redirects=True — в read_file, create_file (upload), и при скачивании из публичного link.
Не забывайте этот флаг
Если делаешь свой код поверх стратегии (например, прямой fetch на Яндекс.Диск) — follow_redirects=True обязателен, иначе будут странные 302 в логах и пустые файлы.
Структура папок¶
Та же логика, что и в Google: pattern_root + pattern_record из AttachmentRoute. Но без аналога Shared Drive — у Яндекс.Диска один корень /Disk/ (или другая стартовая папка, если задана в настройках).
/Disk/
└── Sales Orders/ ← pattern_root
├── SO-0000042-ClientA/ ← pattern_record
│ ├── contract.pdf
│ └── invoice.pdf
└── SO-0000043-ClientB/
Создание папок рекурсивно¶
Яндекс.Диск API не создаёт промежуточные папки при PUT /resources?path=/A/B/C. Если /A/B не существует, вернёт 409. Стратегия обходит это через _ensure_folder_exists:
async def _ensure_folder_exists(self, path: str):
"""Рекурсивно создаёт всё дерево, начиная от ближайшей существующей папки."""
parts = path.strip("/").split("/")
current = ""
for part in parts:
current = f"{current}/{part}"
# Пытаемся создать; если 409 (уже есть) — игнорируем
await self._create_folder_if_not_exists(current)
Прочие методы¶
create_file— двухфазный upload: получаем upload_url через/resources/upload, потом PUT с файлом на этот URL.read_file— получаем download_url через/resources/download, потом GET (с follow_redirects).update_file— Яндекс.Диск перезаписывает файл по тому же пути. Опцияoverwrite=true.delete_file— DELETE/resources?path=.... Файл попадает в корзину; есть опцияpermanently=trueдля жёсткого удаления.move_file— POST/resources/move?from=...&path=.... Используется при переименовании папок (enable_routes_cron).
Лимиты¶
- API: 40 запросов/сек на токен. На массовых импортах FARA вставляет sleep между запросами.
- Размер файла: 50 ГБ через resumable upload, 1 ГБ через простой PUT. Стратегия использует resumable.
- Объём диска: зависит от тарифа Яндекс 360. Бесплатный — 5 ГБ.
Когда лучше Google¶
Сравнение по делу:
| Критерий | Google Drive | Яндекс.Диск |
|---|---|---|
| Работа из РФ | требует обходов | напрямую |
| Shared Drives | да (Workspace) | нет |
| Стабильность ID | да | нет (путь = ID) |
| Сложность OAuth | средняя | средняя (одинаково) |
| Latency из РФ | 200-500 ms | 50-150 ms |
| Цена за ГБ | выше | ниже |
Известные особенности¶
Async против google's sync SDK
Стратегия работает асинхронно через httpx.AsyncClient — не нужны asyncio.to_thread()-обёртки как в Google. Это примерно вдвое быстрее на bulk-операциях.
Cyrillic в путях
Яндекс.Диск принимает кириллические имена папок и файлов нормально. Но в URL они должны быть percent-encoded. httpx делает это сам при передаче через params={"path": "..."}, но если строишь URL вручную — urllib.parse.quote(path).