Заметки
Поле типа Файл и поле типа Файл Диска: в чём разница
Чем отличается обычное файловое поле от поля Файл Диска: ID файла, объект Диска, прикреплённый объект и частые ошибки при получении ссылки.
У файлов в Битрикс24 легко перепутать несколько разных ID.
Обычное поле Файл работает с загруженным файлом как с файловой записью.
Поле Файл Диска связано с объектом Диска. А прикреплённый объект — это вообще
отдельная запись связи между файлом Диска и задачей, комментарием, CRM-сущностью или другим объектом.
Задача
В пользовательских полях, задачах, комментариях и CRM можно встретить похожие файловые значения: просто ID файла, ID объекта Диска или ID прикрепления.
Из-за этого часто появляется ошибка: разработчик берёт число из поля, считает его ID
файла и пытается получить путь через CFile::GetPath. Для обычного поля
Файл это может сработать, а для файла Диска или прикреплённого объекта —
уже нет.
Чтобы не путаться, полезно разделять три сущности:
- обычный файл — запись файловой системы Битрикса;
- объект Диска — файл как документ в модуле Диск;
- прикреплённый объект — связь файла Диска с задачей, CRM, комментарием или другим объектом.
Поле типа Файл
Обычное поле типа Файл не связано с Диском. При загрузке через REST
в него обычно передают файл в виде Base64.
Для универсальных методов CRM файл в такое поле можно передать массивом, где первый элемент — имя файла, второй — содержимое в Base64:
BX24.callMethod(
'crm.item.add',
{
entityTypeId: 128,
fields: {
title: 'Элемент с файлом',
ufCrm_123456: [
'contract.pdf',
'base64_encoded_content_here',
],
},
},
function (result) {
if (result.error()) {
console.error(result.error());
return;
}
console.log(result.data());
}
); Если поле множественное, передаётся массив таких файлов:
BX24.callMethod(
'crm.item.add',
{
entityTypeId: 128,
fields: {
title: 'Элемент с несколькими файлами',
ufCrm_123456: [
[
'contract.pdf',
'base64_1',
],
[
'act.pdf',
'base64_2',
],
],
},
},
function (result) {
if (result.error()) {
console.error(result.error());
return;
}
console.log(result.data());
}
);
В коробке такой файл обычно можно получить через CFile, если у вас есть
именно ID файловой записи:
use Bitrix\Main\Loader;
const FILE_ID = 123;
Loader::includeModule('main');
$file = CFile::GetByID(FILE_ID)->Fetch();
echo '<pre>';
print_r([
'ID' => $file['ID'] ?? null,
'FILE_NAME' => $file['FILE_NAME'] ?? null,
'CONTENT_TYPE' => $file['CONTENT_TYPE'] ?? null,
'SRC' => CFile::GetPath(FILE_ID),
]);
echo '</pre>'; Такой подход подходит для обычных файловых пользовательских полей, старых свойств инфоблоков, картинок товаров и похожих сценариев, где файл хранится как обычный файл, а не как документ Диска.
Поле типа Файл Диска
Поле типа Файл Диска, или Файл (диск), работает иначе.
Оно связано с модулем Диск, поэтому значение относится к объекту Диска.
В такое поле нельзя просто положить Base64 так же, как в обычное файловое поле. Сначала файл загружают на Диск:
BX24.callMethod(
'disk.folder.uploadfile',
{
id: 15,
data: {
NAME: 'contract.pdf',
},
fileContent: [
'contract.pdf',
'base64_encoded_content_here',
],
},
function (result) {
if (result.error()) {
console.error(result.error());
return;
}
console.log(result.data());
}
);
После загрузки с файлом можно работать как с объектом Диска. В REST для этого есть,
например, метод disk.file.get:
BX24.callMethod(
'disk.file.get',
{
id: 9043,
},
function (result) {
if (result.error()) {
console.error(result.error());
return;
}
console.log(result.data());
}
);
Ответ по файлу Диска может содержать не только ID объекта Диска, но и внутренний
FILE_ID, размер, имя, ссылку на скачивание и другие данные.
В коробке можно получить объект Диска через D7:
use Bitrix\Main\Loader;
use Bitrix\Disk\File;
const DISK_OBJECT_ID = 9043;
Loader::includeModule('disk');
$disk_file = File::getById(DISK_OBJECT_ID);
if (!$disk_file) {
echo 'Файл Диска не найден';
return;
}
echo '<pre>';
print_r([
'DISK_OBJECT_ID' => $disk_file->getId(),
'NAME' => $disk_file->getName(),
'FILE_ID' => $disk_file->getFileId(),
]);
echo '</pre>';
Здесь DISK_OBJECT_ID — это ID объекта Диска. А FILE_ID —
внутренняя файловая запись, которая лежит ниже уровнем. Эти значения не нужно смешивать.
Прикреплённый объект
Прикреплённый объект — это не сам файл. Это запись связи, которая соединяет файл Диска с другой сущностью.
Например, файл может быть прикреплён к задаче, комментарию, сообщению или CRM-объекту. В таком случае в поле или методе может вернуться не ID файла, а ID прикрепления.
В REST информацию о такой связи можно получить через disk.attachedObject.get:
BX24.callMethod(
'disk.attachedObject.get',
{
id: 423,
},
function (result) {
if (result.error()) {
console.error(result.error());
return;
}
console.log(result.data());
}
);
В коробке похожую задачу можно решить через Bitrix\Disk\AttachedObject:
use Bitrix\Main\Loader;
use Bitrix\Disk\AttachedObject;
const ATTACHED_OBJECT_ID = 423;
Loader::includeModule('disk');
$attached_object = AttachedObject::getById(ATTACHED_OBJECT_ID);
if (!$attached_object) {
echo 'Прикреплённый объект не найден';
return;
}
$disk_file = $attached_object->getFile();
if (!$disk_file) {
echo 'Файл Диска не найден';
return;
}
echo '<pre>';
print_r([
'ATTACHED_OBJECT_ID' => $attached_object->getId(),
'DISK_OBJECT_ID' => $disk_file->getId(),
'FILE_ID' => $disk_file->getFileId(),
'NAME' => $disk_file->getName(),
]);
echo '</pre>';
Такая цепочка важна: сначала прикреплённый объект, потом файл Диска, потом уже внутренний
файловый ID или ссылка. Если сразу передать ID прикрепления в CFile::GetPath,
результат может быть пустым.
Как не перепутать ID
Главная ошибка — видеть число и сразу считать, что это ID файла для CFile.
В файловых сценариях Битрикса это не всегда так.
Например, такой код может не сработать, если 423 — это ID прикреплённого
объекта, а не ID файла:
const ATTACHED_OBJECT_ID = 423;
echo CFile::GetPath(ATTACHED_OBJECT_ID); Правильная логика другая:
// ATTACHED_OBJECT_ID — это ID связи.
// Сначала нужно получить прикреплённый объект,
// потом файл Диска,
// потом внутренний FILE_ID или ссылку через инструменты Диска. Если непонятно, с каким типом поля вы работаете, сначала получите описание полей:
BX24.callMethod(
'crm.item.fields',
{
entityTypeId: 128,
},
function (result) {
if (result.error()) {
console.error(result.error());
return;
}
console.log(result.data());
}
);
Для обычного поля Файл думайте в сторону Base64 при загрузке и
CFile при работе в коробке. Для поля Файл Диска думайте
в сторону объекта Диска и методов disk.*. Для файлов, прикреплённых
к задачам, комментариям и другим объектам, отдельно учитывайте ID прикрепления.
Проще всего держать в голове такую цепочку: attached object — это связь,
disk object — это файл в Диске, file ID — это внутренняя
файловая запись. В разных методах может вернуться любой из этих уровней.