web-dev-qa-db-fra.com

Comment faire le téléchargement de fichiers dans une fonction de contrôleur?

J'ai posé la question sur le téléchargement de fichiers lors de la soumission d'un formulaire .

Maintenant, je veux clarifier comment le faire dans le cas de la fonction de contrôleur. Autrement dit, un contrôleur est appelé et sa fonction est en cours d'exécution.

Dans le formulaire, le téléchargement du fichier de fonction commence lors de l'exécution de la $form_state->setResponse($response);

Comment le démarrer dans la fonction contrôleur?

J'ai essayé d'utiliser $response->send(); mais il envoie un fichier avec des données erronées et une autre taille.

6
Yakimkin Roman

N'envoyez jamais la réponse avec $response->send(). Renvoyez plutôt la réponse:

use Symfony\Component\HttpFoundation\Response;

public function myController() {
    $response = new Response();
    // prepare $response
    return $response;
  }

BTW, c'est un standard Symfony Controller . Le fait que vous puissiez également renvoyer le contenu principal dans un tableau de rendu est dû au fait que Drupal a ajouté un abonné aux événements, qui convertit le contenu principal en une réponse avec la page html à thème.


Cela fonctionne pour toutes les réponses, dans votre cas par exemple pour une réponse de fichier binaire:

Drupal\system\FileDownloadController :: download ():

  public function download(Request $request, $scheme = 'private') {
    $target = $request->query->get('file');
    // Merge remaining path arguments into relative file path.
    $uri = $scheme . '://' . $target;

    if (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) {
      // Let other modules provide headers and controls access to the file.
      $headers = $this->moduleHandler()->invokeAll('file_download', [$uri]);

      foreach ($headers as $result) {
        if ($result == -1) {
          throw new AccessDeniedHttpException();
        }
      }

      if (count($headers)) {
        // \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
        // sets response as not cacheable if the Cache-Control header is not
        // already modified. We pass in FALSE for non-private schemes for the
        // $public parameter to make sure we don't change the headers.
        return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
      }

      throw new AccessDeniedHttpException();
    }

    throw new NotFoundHttpException();
  }
7
4k4

Mon chemin dans Drupal 8 contrôleur;

use Symfony\Component\HttpFoundation\BinaryFileResponse;

$uri = 'public://' . $fileName;

$headers = array(
        'Content-Type'     => 'application/pdf',
        'Content-Disposition' => 'attachment;filename="'.$fileName.'"');

return new BinaryFileResponse($uri, 200, $headers, true);
2
Tien Wang