1

I want to download a Drupal page to a Word document in an Event Subscriber. The code I'm starting with will download a document which msword will open. Here's the original code:

protected function setResponseContentToWordDocument(ResponseEvent $event) {
  // Get response.
  $response = $event->getResponse();

  // Get response's HTML.
  $html = $this->getResponseHtml($response);

  // Update headers.
  $response->headers->set('Content-Length', strlen($html));
  $response->headers->set('Content-Type', 'application/msword');
  $response->headers->set('Content-Disposition', 'attachment; filename=' . MskString::filename('word_doc.doc'));

  // Set content to html.
  $response->setContent($html);
}

But the response html includes everything, which is too much. I would like to try the phpoffice/phpword library which I've used in the past in controllers.

The problem is the file is silently downloading to the /tmp directory, and not downloading in the browser. Here's the code:

  protected function setResponseContentToWordDocument(ResponseEvent $event) {
    global $base_url;

    $filename = 'my_file';

    // Create a new Word document.
    $php_word = new PhpWord();

    // Add styles.
   ...

   $section = $php_word->addSection();

   $node = \Drupal::routeMatch()->getParameter('node');
   $html = $node->body->value;

   Html::addHtml($section, $html, FALSE, FALSE);

   // Save the document as OOXML file.
   $writer = IOFactory::createWriter($php_word, 'Word2007');

   // Create a temporary file in the system.
   $temp_file = \Drupal::service('file_system')->getTempDirectory() . '/' . $filename . '.docx';

   // Write in the temporary filepath.
   $writer->save($temp_file);

   // Send the temporary file as response (as an attachment).
   $response = new BinaryFileResponse($temp_file);
   $response->setContentDisposition(
     ResponseHeaderBag::DISPOSITION_ATTACHMENT,
     $filename . '.docx'
   );
   $response->deleteFileAfterSend(TRUE);

   return $response;
}

The above code downloads my_file.docx to the /tmp directory. If change return $response; to $response->setContent($temp_file);, a LogicException: The content cannot be set on a BinaryFileResponse instance. error is thrown. How can I download the word file in the Event Subscriber like in the Controller?

2
  • 2
    Try $event->setResponse($response); instead of the return
    – Clive
    Commented Jul 9, 2022 at 19:24
  • Perfect. Thank you.
    – esod
    Commented Jul 10, 2022 at 9:34

0

Your Answer

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

Browse other questions tagged or ask your own question.