Media File Versioning Setup in 1C-Bitrix
Media file versioning is the ability to save the history of file changes, roll back to a previous version, and track who made edits and when. Bitrix does not include such a mechanism in the fileman module by default. Out of the box, when a file is overwritten, the old version is permanently deleted.
How File Storage Works in Bitrix
All files are registered in the b_file table. When a file is "updated" through the standard Bitrix interface, a new record is created in b_file with a new ID, while the old file is physically deleted from disk via CFile::Delete(). References to the old FILE_ID in other tables are updated in a chain — this is why there is no history.
Versioning Architecture
Versioning requires an additional history table:
CREATE TABLE bl_file_versions (
id INT AUTO_INCREMENT PRIMARY KEY,
medialib_id INT NOT NULL, -- ID of b_medialib_item element
file_id INT NOT NULL, -- ID in b_file (old version)
version INT NOT NULL DEFAULT 1,
created_by INT NOT NULL, -- b_user.ID
created_at DATETIME NOT NULL,
comment VARCHAR(500),
INDEX idx_medialib (medialib_id, version)
);
Logic: when a file in the Media Library is updated, the old record from b_file and the physical file are not deleted — instead, the FILE_ID is written to bl_file_versions. The current version remains in b_medialib_item.FILE_ID, and all previous versions are stored in the history table.
Intercepting the Update Event
The event handler is registered in init.php or in a module:
AddEventHandler('fileman', 'OnMedialibItemUpdate', 'SaveFileVersion');
function SaveFileVersion(int $itemId, array $oldFields): void {
if (empty($oldFields['FILE_ID'])) return;
global $USER;
$DB->Query("INSERT INTO bl_file_versions
(medialib_id, file_id, version, created_by, created_at)
SELECT " . intval($itemId) . ", " . intval($oldFields['FILE_ID']) . ",
COALESCE(MAX(version), 0) + 1, " . (int)$USER->GetID() . ", NOW()
FROM bl_file_versions WHERE medialib_id = " . intval($itemId));
}
The OnMedialibItemUpdate event fires before the new data is written, making it possible to save the FILE_ID of the old version.
Physical Storage of Version Files
Version files are stored in /upload/fileman/versions/{item_id}/v{N}/. On rollback, a new record is created in b_file and the file path is restored. Physical deletion of old versions only occurs on an explicit "Clear history" action — not automatically.
To save disk space, only the last N versions can be retained. An agent runs daily to check the bl_file_versions table and delete versions older than the threshold:
$maxVersions = COption::GetOptionInt('mymodule', 'max_file_versions', 10);
Version History and Rollback Interface
A "Version History" button is added to the Media Library admin interface, opening a list with date, author, and a "Restore" button. Rollback means creating a new b_file based on the version file and updating b_medialib_item.FILE_ID.
| Operation | Method |
|---|---|
| Save version | OnMedialibItemUpdate event |
| Get history | SELECT from bl_file_versions |
| Roll back version | CMedialibItem::Update() + CFile::MakeFileArray() |
| Delete version | CFile::Delete() + DELETE from bl_file_versions |
What Is Included in the Setup
- Creating the
bl_file_versionstable and indexes - Writing the
OnMedialibItemUpdateevent handler - Configuring physical storage of version files
- Admin interface for viewing history and rolling back
- Agent for cleaning up old versions based on a configurable limit

