Work with files
A managed file is a file entity that wraps bytes on disk, so the file takes part in usage tracking, access control, and cleanup. This guide writes, addresses, and accepts managed files. Reach for unmanaged filesystem calls only for throwaway temp files.
Create files from your code, turn their URIs into URLs visitors can use, and accept uploads in a form. The worked example is a service that writes a report file and returns its URL.
Prerequisites
Section titled “Prerequisites”- A custom module, per Scaffold a module.
- The core File module installed (
drush pm:install file). - Services and dependency injection for the injected services below.
Write a managed file
Section titled “Write a managed file”Inject file.repository and call writeData(). It saves the bytes and returns a saved file entity in one step; file_system::prepareDirectory() makes sure the destination exists first.
/** * Writes generated content to managed files. * * Prefer the file.repository service over raw filesystem calls: it writes * the bytes AND creates a managed File entity, so the file participates in * usage tracking, access, and cleanup. */final class ReportWriter {
public function __construct( private readonly FileRepositoryInterface $fileRepository, private readonly FileSystemInterface $fileSystem, private readonly FileUrlGeneratorInterface $fileUrlGenerator, ) {}
/** * Writes a report and returns the managed file. */ public function write(string $contents): FileInterface { // Make sure the target directory exists and is writable. $directory = 'public://reports'; $this->fileSystem->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY);
// writeData() saves the bytes and returns a saved File entity. return $this->fileRepository->writeData( $contents, $directory . '/report.txt', FileExists::Replace, ); }The public:// scheme is a stream wrapper pointing at the public files directory; use private:// for files that must run through access checks. FileExists::Replace overwrites; the default Rename writes report_0.txt instead.
Generate a URL
Section titled “Generate a URL”A file’s URI (public://reports/report.txt) is not a URL. Resolve it with file_url_generator.
/** * Returns a browser-usable URL for a managed file. */public function url(FileInterface $file): string { // generateAbsoluteString() resolves the public:// (or private://) URI // through the active stream wrapper into a real URL. return $this->fileUrlGenerator->generateAbsoluteString($file->getFileUri());}For a public file this returns a direct URL; for a private:// file it returns a route that runs file-download access checks before serving the bytes.
Accept an upload
Section titled “Accept an upload”In a form, the managed_file element renders an upload widget and stores the result as a file entity. Set #upload_location to the destination scheme and directory, and #upload_validators to constrain type and size:
$form['attachment'] = [ '#type' => 'managed_file', '#title' => $this->t('Attachment'), '#upload_location' => 'public://uploads', '#upload_validators' => [ 'FileExtension' => ['extensions' => 'pdf txt'], ],];Uploaded files start temporary and are deleted by cron unless you mark them permanent ($file->setPermanent(); $file->save();) and record usage, so Drupal knows something still references them. See Forms for the surrounding form.
Verify
Section titled “Verify”Run the service and confirm the managed file exists:
ddev drush php:eval "\$f = \Drupal::service('howto_files.report_writer')->write('hi'); echo \$f->getFileUri();"prints public://reports/report.txt, and the file appears under web/sites/default/files/reports/.
Variations
Section titled “Variations”Private files
Section titled “Private files”Set $settings['file_private_path'] (outside the web root) and write to private://. Access then runs through hook_file_download() implementations rather than being served directly. See the security checklist.
Images
Section titled “Images”Image files are managed files plus an image style pipeline. See Images and media.
Related
Section titled “Related”- Render array properties for the
managed_fileelement. - Forms for handling uploads in a form.
- The
file API topicon api.drupal.org.
Was this page helpful?
Drupal is a registered trademark of Dries Buytaert.