#Работа с файлами Диска
Сложность: beginner | Скоупы: disk | Стек: cURL / Node.js
#Что делаем
Управляем хранилищами, папками и файлами Bitrix24 Диска через Entity API. Получаем список хранилищ, просматриваем содержимое корневой папки (через обходной путь), создаём подпапки, получаем информацию о файлах. Примеры даны в cURL и Node.js.
Ограничение: загрузка файлов (
disk.folder.uploadfile) пока не покрывается Entity API. Этот метод требует multipart-загрузку и не имеет entity-обёртки. Когда обёртка появится, рецепт будет обновлён.
#Доступные entity-эндпоинты
| Entity | Эндпоинт | Операции |
|---|---|---|
| storages | GET /v1/storages, GET /v1/storages/:id |
list, get (только чтение) |
| folders | GET /v1/folders, GET /v1/folders/:id, POST /v1/folders, PATCH /v1/folders/:id, DELETE /v1/folders/:id |
list, get, create, update, delete |
| files | GET /v1/files, GET /v1/files/:id, PATCH /v1/files/:id, DELETE /v1/files/:id |
list, get, update, delete (без create) |
#Необходимо
- API-ключ Вайбкод с правами
disk - cURL (установлен в большинстве ОС) или Node.js 18+
#Полный код
#!/bin/bash
# disk-operations.sh
# Операции с Bitrix24 Диском через Entity API
API_KEY="${VIBE_API_KEY}"
BASE_URL="${VIBE_BASE_URL}"
# ──────────────────────────────────────────
# 1. Получаем список хранилищ
# GET /v1/storages
# ──────────────────────────────────────────
echo "Список хранилищ:"
curl -s -H "X-Api-Key: ${API_KEY}" \
"${BASE_URL}/v1/storages" | python3 -m json.tool
# Ответ содержит поля: id, name, entityType, entityId, rootObjectId
# rootObjectId — это ID корневой папки хранилища (нужен дальше)
# ──────────────────────────────────────────
# 2. Получаем конкретное хранилище и его rootObjectId
# GET /v1/storages/:id
# ──────────────────────────────────────────
STORAGE_ID=1
echo -e "\nХранилище #${STORAGE_ID}:"
curl -s -H "X-Api-Key: ${API_KEY}" \
"${BASE_URL}/v1/storages/${STORAGE_ID}" | python3 -m json.tool
# ──────────────────────────────────────────
# 3. Содержимое корневой папки хранилища
# Метода disk.storage.getchildren нет в Entity API.
# Обходной путь: берём rootObjectId из хранилища
# и запрашиваем GET /v1/folders?filter[parentId]=ROOT_OBJECT_ID
# ──────────────────────────────────────────
ROOT_FOLDER_ID=3 # rootObjectId из шага 2
echo -e "\nСодержимое корневой папки #${ROOT_FOLDER_ID}:"
curl -s -H "X-Api-Key: ${API_KEY}" \
"${BASE_URL}/v1/folders?filter[parentId]=${ROOT_FOLDER_ID}" | python3 -m json.tool
# ──────────────────────────────────────────
# 4. Создаём подпапку
# POST /v1/folders
# parentId — ID родительской папки (rootObjectId или любая другая)
# ──────────────────────────────────────────
echo -e "\nСоздаём папку 'Документы клиентов':"
curl -s -X POST "${BASE_URL}/v1/folders" \
-H "X-Api-Key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"parentId\": ${ROOT_FOLDER_ID},
\"name\": \"Документы клиентов\"
}" | python3 -m json.tool
# ──────────────────────────────────────────
# 5. Список файлов
# GET /v1/files
# ──────────────────────────────────────────
echo -e "\nФайлы на диске:"
curl -s -H "X-Api-Key: ${API_KEY}" \
"${BASE_URL}/v1/files?limit=10" | python3 -m json.tool
# ──────────────────────────────────────────
# 6. Информация о конкретном файле
# GET /v1/files/:id
# ──────────────────────────────────────────
FILE_ID=42
echo -e "\nФайл #${FILE_ID}:"
curl -s -H "X-Api-Key: ${API_KEY}" \
"${BASE_URL}/v1/files/${FILE_ID}" | python3 -m json.tool
# ──────────────────────────────────────────
# 7. Пакетный запрос: получить хранилища + файлы за один вызов
# POST /v1/batch (entity-формат)
# ──────────────────────────────────────────
echo -e "\nПакетный запрос — хранилища + файлы:"
curl -s -X POST "${BASE_URL}/v1/batch" \
-H "X-Api-Key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"calls": [
{ "entity": "storages", "action": "list" },
{ "entity": "files", "action": "list", "params": { "limit": 5 } }
]
}' | python3 -m json.tool
// disk-operations.js
// Node.js: работа с Диском через Entity API
const API_KEY = process.env.VIBE_API_KEY;
const BASE_URL = process.env.VIBE_BASE_URL;
const HEADERS = {
'X-Api-Key': API_KEY,
'Content-Type': 'application/json',
};
// Хелпер для GET-запросов
async function apiGet(path) {
const response = await fetch(`${BASE_URL}${path}`, {
headers: { 'X-Api-Key': API_KEY },
});
return response.json();
}
// Хелпер для POST-запросов
async function apiPost(path, body) {
const response = await fetch(`${BASE_URL}${path}`, {
method: 'POST',
headers: HEADERS,
body: JSON.stringify(body),
});
return response.json();
}
// 1. Список хранилищ (GET /v1/storages)
async function listStorages() {
console.log('Хранилища:');
const { data } = await apiGet('/v1/storages');
for (const s of data) {
console.log(` [${s.id}] ${s.name} (${s.entityType}) — корневая папка: ${s.rootObjectId}`);
}
return data;
}
// 2. Содержимое корневой папки хранилища
// Обходной путь: storage.rootObjectId → GET /v1/folders?filter[parentId]=...
async function listStorageRootContents(storageId) {
console.log(`\nСодержимое хранилища #${storageId}:`);
// Получаем хранилище, чтобы узнать rootObjectId
const { data: storage } = await apiGet(`/v1/storages/${storageId}`);
const rootFolderId = storage.rootObjectId;
console.log(` Корневая папка: #${rootFolderId}`);
// Запрашиваем дочерние элементы корневой папки
const { data: children } = await apiGet(
`/v1/folders?filter[parentId]=${rootFolderId}`
);
for (const item of children) {
console.log(` [${item.id}] ${item.name}`);
}
return { rootFolderId, children };
}
// 3. Создание подпапки (POST /v1/folders)
async function createFolder(parentId, folderName) {
console.log(`\nСоздаём папку "${folderName}" в папке #${parentId}...`);
const { data } = await apiPost('/v1/folders', {
parentId,
name: folderName,
});
console.log(` Папка создана: id=${data.id}`);
return data;
}
// 4. Информация о файле (GET /v1/files/:id)
async function getFileInfo(fileId) {
const { data } = await apiGet(`/v1/files/${fileId}`);
console.log(`\nФайл #${fileId}: ${data.name} (${data.size} байт)`);
return data;
}
// 5. Список файлов с фильтром (GET /v1/files)
async function listFiles(folderId) {
console.log(`\nФайлы в папке #${folderId}:`);
const { data } = await apiGet(
`/v1/files?filter[folderId]=${folderId}`
);
for (const f of data) {
console.log(` [${f.id}] ${f.name} — ${f.size} байт`);
}
return data;
}
// 6. Пакетный запрос: хранилища + файлы за один вызов
// POST /v1/batch (entity-формат)
async function batchDiskInfo() {
console.log('\nПакетный запрос:');
const result = await apiPost('/v1/batch', {
calls: [
{ entity: 'storages', action: 'list' },
{ entity: 'files', action: 'list', params: { limit: 5 } },
],
});
const [storagesResult, filesResult] = result.data.results;
console.log(` Хранилищ: ${storagesResult.data?.length ?? 0}`);
console.log(` Файлов (первые 5): ${filesResult.data?.length ?? 0}`);
return result.data;
}
// 7. Переименование файла (PATCH /v1/files/:id)
async function renameFile(fileId, newName) {
console.log(`\nПереименование файла #${fileId} → "${newName}"...`);
const response = await fetch(`${BASE_URL}/v1/files/${fileId}`, {
method: 'PATCH',
headers: HEADERS,
body: JSON.stringify({ name: newName }),
});
const { data } = await response.json();
console.log(` Готово: ${data.name}`);
return data;
}
// Демонстрация
async function demo() {
// Список хранилищ
const storages = await listStorages();
if (storages.length === 0) {
console.log('Хранилищ не найдено');
return;
}
// Содержимое корневой папки первого хранилища
const storageId = storages[0].id;
const { rootFolderId } = await listStorageRootContents(storageId);
// Создаём папку в корне хранилища
const folder = await createFolder(rootFolderId, `Проект_${Date.now()}`);
// Пакетный запрос
await batchDiskInfo();
console.log('\nВсе операции выполнены.');
console.log('Загрузка файлов (disk.folder.uploadfile) пока не поддерживается через Entity API.');
}
demo().catch(console.error);
#Как это работает
Список хранилищ —
GET /v1/storagesвозвращает все доступные хранилища (личное, общее, хранилища отделов). Ключевое поле:rootObjectId— ID корневой папки.Содержимое хранилища — прямого эндпоинта
disk.storage.getchildrenв Entity API нет. Обходной путь:- Получаем хранилище:
GET /v1/storages/:id - Извлекаем
rootObjectId - Запрашиваем содержимое:
GET /v1/folders?filter[parentId]=<rootObjectId>
- Получаем хранилище:
Создание папки —
POST /v1/foldersс параметрамиparentIdиname. Можно создавать вложенные структуры, указывая ID родительской папки.Работа с файлами —
GET /v1/files(список),GET /v1/files/:id(информация),PATCH /v1/files/:id(переименование),DELETE /v1/files/:id(удаление).Пакетные запросы —
POST /v1/batchпринимает entity-формат:{ entity: "storages", action: "list" }. До 50 вызовов за один запрос, одна единица rate-limit.
#Ограничения
| Операция | Статус | Комментарий |
|---|---|---|
Загрузка файла (disk.folder.uploadfile) |
Недоступна | Метод требует multipart-загрузку, entity-обёртки нет |
disk.storage.getchildren |
Недоступна | Используйте обходной путь через rootObjectId + GET /v1/folders |
Создание файла (POST /v1/files) |
Недоступна | Файлы создаются только через загрузку |
| Создание/изменение хранилища | Недоступна | Хранилища доступны только для чтения |
#Что можно улучшить
- Добавить рекурсивный обход вложенных папок для полной структуры диска
- Автоматически создавать структуру папок по шаблону (например, для каждого клиента)
- Комбинировать с CRM: при создании сделки автоматически создавать папку и добавлять комментарий в таймлайн с ссылкой на неё