Why are $_Files and/or HTTPFoundationFileBag 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 SymfonyComponentHTTPFoundationFileBag
from within a custom module controller.
The exact location of the issue seems to be in SymfonyComponentHttpKernelHttpKernel
-> 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 SymfonyComponentHttpFoundationFileUploadedFile $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