Why are $_Files and/or HTTPFoundation\FileBag invalid in custom module Controller?
I have noticed a very strange issue with accessing an individual file from the $_FILES
object or the Symfony derived \Symfony\Component\HTTPFoundation\FileBag
from within a custom module controller.
The exact location of the issue seems to be in Symfony\Component\HttpKernel\HttpKernel
-> handleRaw
Specifically, the file exists prior dispatching the KernelEvent::REQUEST
but it does not after.
// request
$event = new GetResponseEvent($this, $request, $type);
// THE FILE EXISTS HERE
// file_exists( $request->files->get(0)->getRealPath()) == TRUE
$this->dispatcher->dispatch(KernelEvents::REQUEST, $event);
// THE FILE DOES NOT EXISTS HERE
// file_exists( $request->files->get(0)->getRealPath()) == FALSE
Here is the entire method for reference also including some code to move the file, which works as expected as long as it is before the event dispatch.
/**
* Handles a request to convert it to a response.
*
* Exceptions are not caught.
*
* @param Request $request A Request instance
* @param int $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
*
* @return Response A Response instance
*
* @throws \LogicException If one of the listener does not behave as expected
* @throws NotFoundHttpException When controller cannot be found
*/
private function handleRaw(Request $request, $type = self::MASTER_REQUEST)
{
$this->requestStack->push($request);
$directory = \Drupal::service('file_system')->realpath(file_default_scheme() . "://");
/* @var \Symfony\Component\HttpFoundation\File\UploadedFile $uploadedFile*/
$uploadedFile = $request->files->get(0);
if (is_uploaded_file($uploadedFile->getRealPath())){
$success = $uploadedFile->move($directory);
}
// request
$event = new GetResponseEvent($this, $request, $type);
$this->dispatcher->dispatch(KernelEvents::REQUEST, $event);
if ($event->hasResponse()) {
return $this->filterResponse($event->getResponse(), $request, $type);
}
// load controller
if (false === $controller = $this->resolver->getController($request)) {
throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', $request->getPathInfo()));
}
$event = new FilterControllerEvent($this, $controller, $request, $type);
$this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event);
$controller = $event->getController();
// controller arguments
$arguments = $this->argumentResolver->getArguments($request, $controller);
$event = new FilterControllerArgumentsEvent($this, $controller, $arguments, $request, $type);
$this->dispatcher->dispatch(KernelEvents::CONTROLLER_ARGUMENTS, $event);
$controller = $event->getController();
$arguments = $event->getArguments();
// call controller
$response = call_user_func_array($controller, $arguments);
// view
if (!$response instanceof Response) {
$event = new GetResponseForControllerResultEvent($this, $request, $type, $response);
$this->dispatcher->dispatch(KernelEvents::VIEW, $event);
if ($event->hasResponse()) {
$response = $event->getResponse();
}
if (!$response instanceof Response) {
$msg = sprintf('The controller must return a response (%s given).', $this->varToString($response));
// the user may have forgotten to return something
if (null === $response) {
$msg .= ' Did you forget to add a return statement somewhere in your controller?';
}
throw new \LogicException($msg);
}
}
return $this->filterResponse($response, $request, $type);
}
I am trying to write a custom GraphQL module
mutation plugin that handles file uploads and unless I can get access to the file object from the POST request, I don't think this will be possible.
Any thoughts are greatly appreciated.
I believe this may be a core issue or an upstream issue with Symfony or at the very least a side effect of the assumptions of how new requests are created.
https://www.drupal.org/project/drupal/issues/2934486#comment-12406531