web-dev-qa-db-ja.com

コントローラー機能でファイルのダウンロードを行う方法は?

フォーム送信時のファイルのダウンロードに関する質問 に質問しました。

ここで、コントローラ機能の場合の方法を明らかにしたいと思います。つまり、いくつかのコントローラーが呼び出され、その機能が実行されています。

フォームの送信関数ファイルのダウンロードは、$form_state->setResponse($response);の実行時に開始されます

コントローラ機能でそれを開始する方法は?

$response->send();を使用しようとしましたが、間違ったデータと別のサイズのファイルが送信されました。

6
Yakimkin Roman

$response->send()を使用して応答を送信しないでください。代わりに応答を返します。

use Symfony\Component\HttpFoundation\Response;

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

ところで、これは標準 Symfony Controller です。 Drupalがイベントサブスクライバーを追加して、メインコンテンツをテーマにしたhtmlページを含む応答に変換するため、レンダー配列でメインコンテンツを返すこともできるというのは事実です。


これはすべての応答で機能します。たとえば、バイナリファイルの応答の場合です。

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

Drupal 8コントローラ;

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