Joomla Media Manager: Adapters, Uploads, Image Editing and Media Fields
|
This content was generated with the assistance of AI and should be verified against the official Joomla documentation before being relied on in production. This sub-section’s Joomla bibliography lists the reference material consulted while preparing these pages. |
This page describes the Joomla Media Manager as it was on 2026-10-30, the date on which its facts were checked against the Joomla! User Guide (https://guide.joomla.org/), the Joomla! Developer Manual and the source tree of the CMS. It was written against Joomla 6.2.x (PHP 8.3 or later); the screens and settings described are the same in the 5.4 security-only line unless a version is named. The running example is the Tallpine Hiking Club site: editors upload trail photographs, board members upload minutes as PDF files, and each trail report carries a GPX track as a media custom field.
The Media Manager is used by four kinds of people. Editors and authors upload, rename and insert files. Site builders decide which folders exist and which file types are allowed. Administrators protect the upload path. Developers add storage back ends and media fields to their own extensions. The sections below follow that order.
What the Media Manager is
The Media component (com_media) manages the images and other files that articles, modules and templates use. The
User Guide stresses one fact that explains much of its design: media are served directly by the web server, not by
Joomla code, so delivering an image costs no PHP execution. The component only helps people organise, upload, edit and
insert files. The files themselves live in ordinary folders of the web root.
By default these folders are images and, since Joomla 5.3, files. The separate top-level media folder holds
the JavaScript, CSS and web assets of Joomla and its extensions and is not a place for uploads; confusing the two is a
common mistake. Folder names become part of public URLs, so the User Guide recommends lowercase names without spaces
or punctuation and hyphens between words (for example trail-reports), and recommends planning the folder tree to
mirror the category structure, because moving an image later breaks the links in articles that point to it.
The Media Manager can be opened in three ways:
-
Content → Media in the administrator menu, as a normal component screen
-
Site panel → Media on the Home Dashboard
-
the CMS Content → Media button of an article edit screen, which opens it in a modal dialog so that a picture can be selected and inserted into the text
The Vue-based interface
Since Joomla 4.0 the Media Manager is a single-page application written with Vue. The server renders almost nothing:
the page loads a Vue application from the media folder, and the application talks to the server through a JSON API
exposed by com_media (the api controller, which forwards each request to the ApiModel). Listing a folder,
creating a folder, uploading, renaming, moving, copying, deleting and saving an edited image are all calls of that API.
The interface is therefore a client of a documented set of server-side classes rather than a set of form posts, and
that is what makes it possible to add storage back ends and editing tools as plugins.
The interface has these parts, all described in the User Guide:
-
a tree in the left column whose roots are the registered storage locations (labelled Local for the local file system), with the folder tree below each root; selecting a folder closes its sibling folders
-
breadcrumbs for moving back up the hierarchy; double-clicking a folder opens it
-
a toolbar with a select-all box, a search box that filters the list as you type, a magnifier that changes the thumbnail size (roughly 2, 4, 6 or 8 items per row, depending on the screen width), a list/thumbnail toggle (the list shows dimensions and file size) and an information icon that opens a side panel with the details of the selected item
-
Create New Folder and Upload buttons, drag-and-drop upload, and Delete, Rename, Edit, Move and Copy actions
-
the Options button, which opens the component options described below
Deleting a folder deletes everything inside it. To empty a folder without deleting it, use the select-all box and delete the items.
Architecture: providers, adapters and the filesystem plugin
The Media Manager separates three concerns: what a storage location is (an adapter), who offers it (a provider) and how
it is shown (the Vue application). The classes live in the namespace Joomla\Component\Media\Administrator.
A provider implements ProviderInterface, with three methods: getID(), getDisplayName() and getAdapters().
An adapter implements AdapterInterface and represents one root. Its methods are getFile(), getFiles(),
getResource(), createFolder(), createFile(), updateFile(), delete(), move(), copy(), getUrl(),
getAdapterName() and search(). Providers are plugins of the filesystem group. When the Media Manager starts it
dispatches the onSetupProviders event with a MediaProviderEvent, and every enabled filesystem plugin registers
itself with the ProviderManager obtained from the event. The manager keys providers by their ID and finds an adapter
from a name of the form provider-account, such as local-images; the part after the first hyphen is the account,
so the account itself may contain hyphens. Unknown providers or accounts raise a ProviderNotFoundException or a
ProviderAccountNotFoundException.
Everywhere the Media Manager refers to a file it uses the combination of the adapter and the path inside it, for
example local-images:/trails/alpine/ridge.jpg. The same notation is stored by media fields (see below).
The FileSystem - Local plugin
The core provider is plg_filesystem_local, a final class Joomla\Plugin\Filesystem\Local\Extension\Local that
extends CMSPlugin and implements SubscriberInterface and ProviderInterface. It subscribes to the single event
onSetupProviders. Its only parameter is a repeatable directories subform, in which every row has a directory
(chosen from the folders that exist in the site root) and a thumbs switch. The default value is:
[{"directory": "images"}, {"directory": "files"}]
For every row with a non-empty directory, getAdapters() creates one LocalAdapter rooted at that folder, with a
fixed thumbnail size of 200 x 200 pixels, and attaches the current user to it. A row without the thumbs flag is
treated as thumbs = 0. Each adapter appears as a root in the Media Manager tree. Adding a row is how a site gets an
additional media root, and the User Guide’s procedure is: create a folder in the site root (for example gpx), open
the FileSystem - Local plugin, press the + button, choose the folder from the list, make sure the plugin is enabled
and save. The folder must not reuse the name of a core Joomla folder.
[
{"directory": "images", "thumbs": 1},
{"directory": "files", "thumbs": 0},
{"directory": "gpx", "thumbs": 0}
]
The Create Thumbnails switch is the thumbs flag. The User Guide explains the effect: Joomla generates previews of at
most 200 pixels in height or width in media/cache/com_media/thumbs, in a tree that mirrors the media folder. The
adapter creates a thumbnail when an image is uploaded or updated and, on demand, the first time a listing finds no
thumbnail. A failure to create one is silent, and the interface then falls back to the original image. Deleting a file
or folder deletes its thumbnails too. Thumbnails speed up folders with many images and are pointless for documents,
which are shown as icons, so the switch is per root.
The files folder introduced in 5.3
Joomla 5.3 added a second default root named files, so that documents such as PDFs are kept apart from pictures. The
release announcement for 5.3 mentions it in a single line. The corresponding options are image_path (default
images) and file_path (default files) in the Media options, and the local plugin lists both folders by
default. Older material describes the situation of Joomla 3 and 4, where both paths pointed to the images folder in a
new installation; the User Guide page on media options still says so. On a current installation, a trail photograph
goes into images and a PDF of the board minutes into files. A site upgraded from an earlier release may not have
the files folder or the second row of the plugin until an administrator creates them.
A custom root is also the right answer to a recurring request: documents that must not live under images, for
example because a reverse proxy serves that folder from a CDN with long cache lifetimes. Remember that every root the
local plugin exposes is a public web folder; the Media Manager has no private storage.
Writing a provider for another storage back end
A developer can offer a different back end, such as an object store, by writing a plugin of the filesystem group. The
plugin below is a minimal provider that exposes a read-write gpx folder with a core LocalAdapter; a real object
store would return its own class implementing AdapterInterface instead.
<?php
namespace Tallpine\Plugin\Filesystem\Gpx\Extension;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Component\Media\Administrator\Event\MediaProviderEvent;
use Joomla\Component\Media\Administrator\Provider\ProviderInterface;
use Joomla\Event\SubscriberInterface;
use Joomla\Plugin\Filesystem\Local\Adapter\LocalAdapter;
defined('_JEXEC') or die;
final class Gpx extends CMSPlugin implements SubscriberInterface, ProviderInterface
{
public function __construct(array $config, private string $rootDirectory)
{
parent::__construct($config);
}
public static function getSubscribedEvents(): array
{
return ['onSetupProviders' => 'onSetupProviders'];
}
public function onSetupProviders(MediaProviderEvent $event): void
{
$event->getProviderManager()->registerProvider($this);
}
public function getID(): string
{
return $this->_name;
}
public function getDisplayName(): string
{
return 'Tallpine GPX tracks';
}
public function getAdapters(): array
{
$adapter = new LocalAdapter($this->rootDirectory . '/gpx/', 'gpx', 0, [200, 200]);
return [$adapter->getAdapterName() => $adapter];
}
}
Source: Joomla Manual: How plugins work
The plugin needs the usual services/provider.php and manifest of a filesystem plugin (see
Plugin Development and Events and
Extension Types, Manifests and Packaging); the core
plg_filesystem_local is the model to copy. The core plugin’s services/provider.php builds the plugin with
(array) PluginHelper::getPlugin('filesystem', 'local') and JPATH_ROOT as the two constructor arguments and then calls
setApplication(); the sketch above assumes the same wiring. The provider ID is the plugin name, so adapters are
addressed as <plugin name>-<adapter name>.
Upload rules: extensions, MIME types and size
Uploads are the dangerous part of any CMS, and Joomla validates them in layers. The settings live in the component
options (the Options button of the Media Manager, or System → Global Configuration → Media), in the component
fieldset of administrator/components/com_media/config.xml.
| Option | Default in 6.2 | Meaning |
|---|---|---|
|
|
Maximum upload size in megabytes. In the helper, 0 means no limit. |
|
|
Folder for non-image files (since 5.3) |
|
|
Folder for images |
|
|
Enables content inspection and the MIME and administrator checks |
|
|
The allowlist of file extensions (shown as Allowed Extensions) |
|
|
Requires the detected MIME type to be in the list below |
|
|
Extensions treated as images |
|
|
Extensions treated as audio |
|
|
Extensions treated as video |
|
|
Extensions treated as documents |
|
empty |
Extensions that pass the extension check and skip the MIME and administrator checks |
|
image, audio, video, Office, PDF, |
Allowed MIME types |
Source: joomla-cms: com_media config.xml
The image_extensions, audio_extensions, video_extensions and doc_extensions options decide what the interface
considers a media file and which filter (images, audio, video, documents) a media field offers; the allowlist
restrict_uploads_extensions decides what may be uploaded at all. A new extension therefore usually has to be added in
two places, and to upload_mime as well. The User Guide’s troubleshooting advice for a rejected upload is to check the
allowed extensions, the legal extension types and the legal MIME types: all three must agree.
What MediaHelper::canUpload() checks
Every upload goes through MediaHelper::canUpload() (called by the local adapter in checkContent(), which first
writes the data to a temporary file). It stops at the first failed step:
-
an empty file name is rejected
-
a name that
File::makeSafe()would change is rejected, so unsafe characters never reach the disk -
a name without an extension is rejected
-
every dot-separated segment of the name is compared with the blocklist of executable extensions, not only the last one, so
shell.php.jpgis refused -
the final extension must be in
restrict_uploads_extensionsorignore_extensions -
the size must not exceed
upload_maxsize -
when
restrict_uploadsis on, the content is inspected. For an allowlisted extension the file must be a real image (detected withexif_imagetype()andgetimagesize()) with a permitted MIME type. For an extension that is not on the allowlist and not ignored, the MIME type is detected withmime_content_type()orfinfoand must be inupload_mime, and the user must havecore.manageoncom_media -
a file with the extension
svgis run through the SVG sanitiser
A failure raises a generic forbidden error (HTTP 403) in the interface and the specific language key in the log; the
exact messages include JLIB_MEDIA_ERROR_WARNFILETYPE, JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE and
JLIB_MEDIA_ERROR_WARNFILETOOLARGE. The Local adapter also protects against path traversal: every path is resolved
with Path::check() against the root of the adapter, search terms containing separators or .. are rejected, and a
move that would change the sanitised name is refused. Copying and moving without the force flag refuse to overwrite an
existing target.
The default of restrict_uploads_extensions in config.xml and the fallback default coded in MediaHelper are
slightly different lists (the helper also lists m4a, mp4a, ogg, mp4v, mpeg and mov). Because the saved
component options take precedence on any site whose options were ever saved, treat the options screen as the
authority and review it after an upgrade.
Letting editors upload GPX files
The Tallpine custom field gpx-file needs GPX uploads. A GPX file is XML, so the detected MIME type is typically
application/xml or text/xml, never an image type. The complete change is to add gpx to
restrict_uploads_extensions and to doc_extensions, add the detected MIME type to upload_mime, and allow the user
group to manage media (for non-allowlisted content the user needs core.manage on Media). When a GPX upload is rejected
with JLIB_MEDIA_ERROR_WARNINVALID_MIMETYPE, the log shows the MIME type that was detected, which is the value to add.
Adding gpx to ignore_extensions would also make it work but disables the MIME and administrator checks for that
extension, which is acceptable only for a type that cannot carry active content.
# Show what the server's libmagic thinks of a sample file before changing upload_mime
file --mime-type tallpine-alpine-loop.gpx
Source: Joomla User Guide: Media Options
SVG files
By default Joomla does not accept SVG. To allow it, add svg to the allowed extensions and to the image extensions,
and image/svg+xml to the MIME list. Since Joomla 4.1 every SVG uploaded through the Media Manager is checked by a
sanitiser, and rules are strict. SVG is XML text, so it can carry cross-site scripting through <script> elements and
event attributes, HTML injection through <foreignObject>, and denial of service through misused xlink:href
references. A file that is refused usually needs cleaning in an editor or an external SVG cleaner. Allow SVG only for
trusted editors, and remember that the sanitiser protects files uploaded through the Media Manager, not files copied to
the folder by FTP.
Permissions
Access to the Media Manager is governed by the ACL of com_media (the Permissions tab of its options): who may
access the component, create folders and upload (core.create), edit (core.edit) and delete (core.delete). The
custom field and media field respect these too: a media field is disabled for a user without core.create on
com_media. The adapter itself performs no ACL checks, so a developer who calls an adapter directly must check
permissions. See Users, Groups, Access Levels and ACL. The
restrict_uploads option stays on for every public site; turning it off removes the content inspection that protects
against a renamed script.
Image editing: crop, resize and rotate
The Media Manager can edit an image in place. Editing tools are plugins of the media-action group: the core ships
crop, resize and rotate. Each plugin extends MediaActionPlugin, which listens to onContentPrepareForm, reacts
only to the form named com_media.file, loads the plugin’s JavaScript module and CSS, and loads an XML form from
plugins/media-action/<name>/form/<name>.xml. The interface then shows one tab per enabled plugin on the Edit screen
of an image. Disabling a plugin in the Plugin Manager removes its tab.
The User Guide describes the three tools:
-
Crop: choose an aspect ratio or none, drag the corners, edges or the inside of the selection, or type the X and Y offsets and the width and height; press Save to apply it.
-
Resize: enter a width and the height follows, keeping the aspect ratio. The resize form also carries a quality slider (1 to 100, default 80). The User Guide warns that the quality control is currently not reliable and that a modified image may end up larger than the original.
-
Rotate: pick an angle, in steps of 90 degrees.
Saving overwrites the file: there is no undo, so edit a copy when the original matters. After a crop the interface may
show stale box values even though the crop was applied. The resize plugin also has a batch fieldset in its own
parameters, a maximum width and a maximum height in pixels: when set, images are scaled down automatically as they are
uploaded, which is the better answer to oversized phone photographs than asking editors to resize by hand.
The save path matters for developers. Editing and uploading go through the ApiModel, which loads the content and
media-action plugin groups and dispatches onContentBeforeSave, onContentAfterSave, onContentBeforeDelete and
onContentAfterDelete with the contexts com_media.file and com_media.folder, so a content plugin can veto or log
an upload. Listing and reading dispatch onFetchMediaItem, onFetchMediaItems and onFetchMediaFileUrl, which let a
plugin change what the interface displays.
Media fields
A media field (form field type media, class Joomla\CMS\Form\Field\MediaField) is the control that opens the
Media Manager in a modal from any form: the intro and full-article images of an article, a module parameter or a
custom field. It renders with the layout joomla.form.field.media. In an XML form it looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="basic">
<field
name="cover_image"
type="media"
label="COM_TALLPINE_FIELD_COVER_IMAGE_LABEL"
types="images"
directory="trails"
preview="tooltip"
/>
<field
name="gpx_file"
type="media"
label="COM_TALLPINE_FIELD_GPX_FILE_LABEL"
types="documents"
directory="gpx"
/>
</fieldset>
</form>
Source: Joomla Manual: Media Form Field
The attributes that matter:
-
types: a comma-separated list chosen fromimages,audios,videos,documentsanddirectories; the default isimages. The permitted extensions of each type come from the extension options above.directorieslets the user pick a folder rather than a file, which is what the media custom field uses for its own Directory parameter. -
directory: the starting folder, relative to the images path, or anadapter:pathstring for another root. It is used only when the folder exists and belongs to a registered local directory. -
preview(true,tooltiporfalse; the default istooltip),preview_widthandpreview_height(default 200 x 200): whether and how a preview is shown. -
widthandheight(default 800 x 500): the size of the modal.
The stored value is a path followed by a fragment that records the adapter and the image size, for example
images/trails/ridge.jpg#joomlaImage://local-images/trails/ridge.jpg?width=1200&height=800. Output code must remove
the fragment before using the value as a URL; HTMLHelper::cleanImageURL() does that and returns the clean URL plus
the width and height, which can be placed on the img element to avoid layout shift. A plain local path (the Joomla 3
format) is still accepted if the file exists, so content from old sites keeps working.
The media custom field
For the Tallpine trail article the site builder creates a custom field GPX file of type Media (the fields plugin
plg_fields_media). Its parameters are Directory (a folder picker restricted to directories, so the editor starts in
gpx), Preview (inline preview of the selected image or not) and Image class, a CSS class added to the img tag on
output; the User Guide’s example is w-25. Custom fields in general are covered in
Custom Fields. The plugin normalises the stored value before output: a JSON value
is decoded, and a legacy plain string is wrapped as an imagefile with an empty alt text.
Accessible images: alt text and the accessiblemedia field
Every informative image needs a text alternative, and every purely decorative image needs an explicit empty one. Joomla supports both in the places where editors work:
-
the article Images and Links tab has an alt text input and a "no description" option for the intro image and for the full-article image
-
the editor’s image dialog asks for an image description and has an "image has no description" option, which emits
alt="" -
the
accessiblemediafield type (Joomla\CMS\Form\Field\AccessiblemediaField, extendingSubformField) is a media field that carries its accessibility information with it. The media custom field is exposed to editors as anaccessiblemediafield, and it is the field type to use in new extensions
The accessiblemedia field builds its subform from the types attribute: for images it shows a media selector named
imagefile, a text field alt_text and a checkbox alt_empty ("no description", for decorative images); for
documents a linktext field; for videos an optional poster selector when video_poster is 1; and for audio a
single file selector. The types attribute was added to this field in 6.1. The stored value is a JSON object, and
the field accepts a legacy plain path by converting it to imagefile with an empty alt_text.
<field
name="hero"
type="accessiblemedia"
label="COM_TALLPINE_FIELD_HERO_LABEL"
types="images"
directory="trails"
/>
<?php
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
defined('_JEXEC') or die;
// $hero is the decoded JSON value of the accessiblemedia field.
$hero = json_decode($this->item->params->get('hero', '{}'), true) ?: [];
if (!empty($hero['imagefile'])) {
$image = HTMLHelper::cleanImageURL($hero['imagefile']);
$alt = empty($hero['alt_empty']) ? ($hero['alt_text'] ?? '') : '';
?>
<img src="<?php echo htmlspecialchars($image->url, ENT_QUOTES, 'UTF-8'); ?>"
alt="<?php echo htmlspecialchars($alt, ENT_QUOTES, 'UTF-8'); ?>"
width="<?php echo (int) $image->attributes['width']; ?>"
height="<?php echo (int) $image->attributes['height']; ?>"
loading="lazy">
<?php
}
Escape the alt text on output as shown: it is editor input. A missing alt_text with alt_empty unset is an editorial
error, not a decorative image; the emitted alt must be a deliberate choice. More on accessibility testing is in
Web Accessibility and on Joomla’s own accessibility settings in
Colour Modes, RTL and Accessibility.
Common errors and pitfalls
-
"This file type is not allowed" for a type that is in the list. The extension must be in the allowlist, in the type list for the field and, when
check_mimeis on, its detected MIME type must be inupload_mime. -
Uploads fail only for large files. The effective limit is the smallest of
upload_maxsize, PHP’supload_max_filesizeandpost_max_size, and the web server’s body limit (see Web Server, Reverse Proxy and HTTPS). -
A thumbnail view that shows broken images is usually a missing GD or Imagick extension, or a read-only
media/cachefolder, because thumbnail failures are silent. -
Moved or renamed images break articles, because articles store paths. Rename within the manager and then fix the links, or keep the folder tree stable from the start.
-
Spaces and capitals in file names. The manager sanitises names and a move that would change the name is refused; rename the file instead.
-
Disabling
restrict_uploadsto make an odd file pass removes the main defence against disguised scripts. -
A custom root that is not listed because the plugin is disabled or the folder does not exist at the site root.
-
Treating the Media Manager as private storage. Every root is web-accessible; confidential files do not belong in it.
Corrections to older books and tutorials
Joomla! 4 Masterclass (2023) is the book that covers articles and the Media Manager in depth, and its screens still
match the current one. It was written before Joomla 5.3 and says nothing of the files folder or of the per-root
thumbnail switch, and it predates the accessiblemedia field and the types attribute added in 6.1. Older books and
tutorials, and the User Guide page on media options, describe a new installation in which both the image path and the
file path point to the images folder; since 5.3 the file path defaults to files. Material written for Joomla 3, with its older image
modal, does not apply to the Vue-based manager.
The 5.x development material in Developing Extensions for Joomla! 5 (2023) is otherwise a good source for media
fields in forms.