advanced_filesystem
Take control of where your files live on disk, find the orphans, sanitize filenames, strip metadata and clean everything up — automatically.
Overview
Advanced File System turns Drupal's file storage into a manageable, observable and maintainable subsystem. It ships a pluggable path strategy API (13 built-in strategies) to control where uploaded files land on disk, a batch migration tool with dry-run preview and confirmation step, a unified dashboard, a detailed file report with filters and CSV / JSON export, upload-time processing hooks (filename sanitization, duplicate resolver, EXIF stripping), and a suite of background services that monitor orphans, record storage growth, run retention rules, deduplicate content and rewrite hardcoded URLs after a migration.
Built around standard Drupal patterns: Plugin API, Batch API, Queue API, Cron, Mail, State and the Symfony EventDispatcher.
Highlights
Path organization
- 13 built-in path strategies — from simple (flat, year) to advanced (CDN hash, date+hash, MIME type, content type, field name, user role, locale-aware).
- Strategy presets — one-click configuration combos for the most common layouts.
- Strategy simulator — enter a fictional file and instantly see the URI every installed strategy would produce, in dry-run mode with no disk writes.
- Cron-based automatic migration — schedule file migration to run automatically on cron with configurable interval and per-run cap.
Visibility & reporting
- Dashboard — single page with stream wrappers, orphan counts, retention queue, migration stats, last rollback / rewrite, lifetime totals and audit-log entries.
- File report — filters (path, MIME, status, size range, field, used / unused), pagination, CSV / JSON export.
- Folder report — recursive size and extension breakdown of any stream wrapper, with top-N largest files.
- Storage growth report — historical snapshots of total storage and file count recorded on every cron run, with delta and percentage-change columns. Up to 90 snapshots retained.
Upload-time processing
- Filename sanitizer — on
hook_file_presave(): transliterate, lowercase, replace whitespace with a configurable separator, strip special characters, enforce max length. Configurable via UI. - Duplicate filename resolver — detects URI collisions in
file_managedand auto-appends a numeric suffix (photo-2.jpg, photo-3.jpg…) instead of overwriting. Toggle via UI. - Media metadata stripper — re-encodes JPEG / PNG / WebP via PHP GD to strip EXIF / IPTC metadata (GPS coordinates, camera model, author name…). Configurable quality and MIME type list. Toggle via UI.
Cleanup & maintenance
- Orphan files monitor — read-only cron email alert when unreferenced file count crosses a configurable threshold.
- Bulk delete orphans — one-click batch deletion of all currently detected orphan files, with two-step confirmation and option to remove only the DB record (keep physical file).
- Retention rules — multi-rule cron actor: delete or quarantine unreferenced files older than N days, per-directory rule patterns, capped per run, optional dry-run and email report.
- Deduplication — SHA-256 hash detection, repoints file_usage and entity references to the canonical fid, optionally marks duplicates as temporary.
- Duplicate file alerts — separate cron-based email notification when duplicate groups exceed a configurable threshold.
Content integrity
- Body reference rewriter — scans
text_long,text_with_summaryand link fields and rewrites hardcoded file URLs using the migration map. Supports relative + absolute URL variants in a single pass, all revisions, diagnose mode, and background processing via Drupal's Queue API. - Integrity check — verifies every
file_managedrow against disk. - Rollback — every migration writes a map row; roll back to original URIs at any time.
Developer experience
- Audit log — every destructive operation recorded with user, timestamp, target, result and JSON details.
- Symfony events — pre / post events for migrate, rollback, dedupe, rewrite and per-file retention.
- Self-diagnosis —
drush advfs:doctorruns a battery of checks and returns a non-zero exit code on failure. Perfect for CI / post-deploy pipelines. - Drush commands for every UI operation, scriptable for CI / CD.
Built-in path strategies
ID Label URI structuredefault
Drupal Default
Respects field directory tokens as Drupal core.
flat
Flat
<scheme>://flat/<filename>
flat_named
Flat (named folder)
<scheme>://<folder>/<filename>
counted
Counted Directory
Field dir + numbered buckets capped at a configurable max.
entity_bundle
Entity / Bundle
<scheme>://<entity_type>/<bundle>/[YYYY-MM/]<filename>
cdn_hash
CDN-friendly content hash
<scheme>://<folder>/<aa>/<bb>/<hash>.<ext> — immutable URLs.
date_hash
Date + partial hash
<scheme>://<folder>/YYYY/MM/<aa>/<bb>/<name--hash>.<ext>
locale_path
Locale-aware
<scheme>://<langcode>/[<field_dir>/]<filename>
content_type
Content type path
<scheme>://<folder>/<content_type>/[YYYY-MM/]<filename>
user_role
User role path
<scheme>://<folder>/<role>/[YYYY-MM/]<filename>
mime_type
MIME type path
<scheme>://<folder>/<images|video|audio|documents|archives|text|other>/[YYYY-MM/]<filename>
year
Year path
<scheme>://<folder>/YYYY/[MM/]<filename>
field_name
Field name path
<scheme>://<folder>/<field_name>/[YYYY-MM/]<filename>
Ship your own strategy from any module using the @PathStrategy annotation — it is automatically picked up by the migration UI and all Drush commands.
Admin pages
- Dashboard —
/admin/reports/advanced_filesystem - Files report —
/admin/reports/advanced_filesystem/files - Folder report —
/admin/reports/advanced_filesystem/folders - Storage growth —
/admin/reports/advanced_filesystem/storage-growth - Migrate Files Strategy —
/admin/config/media/advanced_filesystem/strategy - Cron migration —
/admin/config/media/advanced_filesystem/cron-migration - Strategy simulator —
/admin/config/media/advanced_filesystem/simulator - Orphan and retention settings —
/admin/config/media/advanced_filesystem/orphan-settings - Bulk delete orphans —
/admin/config/media/advanced_filesystem/bulk-delete-orphans - Rollback —
/admin/config/media/advanced_filesystem/rollback - Deduplicate files —
/admin/config/media/advanced_filesystem/dedupe - Duplicate alerts —
/admin/config/media/advanced_filesystem/duplicate-alert - Rewrite embedded URLs —
/admin/config/media/advanced_filesystem/rewrite - Filename sanitizer —
/admin/config/media/advanced_filesystem/sanitizer - File tools —
/admin/config/media/advanced_filesystem/file-tools - Integrity report —
/admin/reports/advanced_filesystem/integrity
Drush commands
- advanced_filesystem:migrate-files — migrate all files (or one field's files) with optional
--strategy,--delete,--dry-run. - advanced_filesystem:rewrite (alias
afr) — rewrite embedded URLs in long-text and link fields. Options:--dry-run,--all-revisions,--entity-type,--field,--list. - advanced_filesystem:check-orphans — force orphan check, bypassing cron throttle.
- advanced_filesystem:run-retention — force retention pass:
--dry-run,--list,--list-rules. - advanced_filesystem:rollback — revert migrations:
--since,--until,--dry-run,--force,--rewrite-bodies. - advanced_filesystem:dedupe — compute hashes and merge duplicate groups.
- advanced_filesystem:check-integrity — verify every
file_managedrow against disk. - advanced_filesystem:folder-report — recursive size / extension breakdown of a stream wrapper.
- advanced_filesystem:doctor (alias
advfs:doctor) — self-diagnosis; exit 1 on FAIL (or WARN with--strict).
Requirements
- Drupal 10 or 11
- PHP 8.1+
- The file module (core)
- Drush 12+ — optional, for CLI commands
- A working MailManager for email notifications
- A configured private filesystem for quarantine
- PHP GD extension for image metadata stripping
Installation
composer require drupal/advanced_filesystem drush en advanced_filesystem -y drush updb drush cr