I am trying to serve files from Amazon S3(s3:// stream wrapper) via system.files / system.private_file_download routes but no matter what I do the scheme is always set to private.

I have tried to use /system/files/s3/file.jpg for system.private_file_download and /system/files/s3?file=file.jpg for system.files

but I always get private scheme.

The system.private_file_download route seems to be completely broken due to htaccess rules(ie. serving image like this won't even make it to the controller) and system.files somehow completely ignores provided scheme argument.

So far I have observed that the routes get matched to requests in exact opposite as one would expect. The system.files route is defined first and it expects only "scheme" url argument(with "private" as default value in controller and also in the route itself), for example /system/files/public and what is provided as "file" query argument is used as target, so /system/files/public?file=foo/bar.jpg should result into public://foo/bar.jpg but instead the system.private_file_download route is used(even though it is defined after the system.files route). This route expects the "filepath" url argument, like /system/files/foo/bar/.jpg, and it automatically uses the private scheme because both of these routes use the same controller but this route does not provide the scheme in its definition or path so the default value from the controller itself is used.

I think the issue here is that the second route is using the filepath: .+ argument mask and therefore will match "better" with the path so it will have more priority over previously defined system.files route.

Also strangely the "filepath" url argument in system.private_file_download route has no match in the controller(\Drupal\system\FileDownloadController::download) so the resulting uri will be simply private:// no matter what values are provided to the route.

I have replaced the public stream wrapper with s3 so all files are now served from remote server and it is working just fine. I was able to get the image styles working(system/files/styles/thumbnail/public/foo/bar.jpg) but I am still not able to serve the original files from under /system/files path as well. Since I need to serve the physical files and not File entities, even if I would switch to private file system the files would not be served because file_file_download() handles only file entities.

I have ended up with custom route. If anyone is interested the important thing is to have two routes(just like the two mentioned above). The second one will transform the url arguments into query argument and return path to the first route. This is done via path_processor_inbound tagged service(see \Drupal\system\PathProcessor\PathProcessorFiles).

1 Answer 1


I looked into this. Long story short, it's a bug in core: https://www.drupal.org/node/2694129. It will be a bit tricky to fix, since it might require API change and not 100% sure when such a change can actually be made.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.