1

I'm trying to create an archive of log files to be downloadable in a form making a custom module in Drupal 9. In the form, the user can change the format of the archive, as per image: Screen of the log form

Here below my code:

private function download($form, $form_state) {
  $format = $form_state->getValue('format');
  $folder = $form_state->getValue('folders');

  $date = new DateTime();
  $date = $date->format("y_m_d_H_i_s");

  $logsDirectory = \Drupal::service('file_system')
    ->realpath($folder . "://logs/");
  //Retrieve all the files in the folder.
  $logs = glob($logsDirectory . "/*.log");

  $archiveName = $date . $format;

  $archive_path = \Drupal::service('file_system')
    ->saveData('', 'temporary://' . $archiveName);
  $archive = \Drupal::service('plugin.manager.archiver')
    ->getInstance(['filepath' => $archive_path]);

  foreach ($logs as $log) {
    $archive->add($log);
  }

  $response = new BinaryFileResponse($archive_path);
  $response->headers->set('Content-type', $this->getContentTypes($format));
  $response->headers->set('Content-Disposition', 'attachment;filename="' . $archive_path . '"');
  $form_state->setResponse($response);
}

Everything is going fine, I managed to achieve a button in this way that, when pressed, downloads the archive with all the log files inside. The problem is that inside of this zip all the files are inside their absolute path, in this way: Tree of files inside the zip

This is because in the ArchiveInterface Class the add method only accepts one parameter, $file_path, and it is not supported to add a second parameter to specify the name of the files. How could I solve this problem, being able of adding inside the archive only the files and not all the subfolders?

1
  • I realised after posting an answer that the user chooses the format, so you need more than Zip. The Zip one is easy, unfortunately the Tar one not so much. The PHP archiver doesn't support what you want so you need to extend it (stackoverflow.com/questions/15831121/…). Let me know if the answer isn't useful at all and I'll delete if so
    – Clive
    Apr 13, 2022 at 19:42

1 Answer 1

0

Drupal's Zip archiver doesn't support that functionality directly, but the underlying PHP ZipArchive it uses does (see ZipArchive::addFile()), and you can get a reference to that object from the Drupal archiver.

For example:

$zip_archive = $archive->getArchive();
foreach ($logs as $log) {
  $zip_archive->addFile($log, basename($log));
}

Bear in mind that this only works well for a glob that brings back unique file names every time. If the structure changes and you end up with subfolders containing files with name clashes, you'll need to update the loop to accommodate, or risk some files not being included.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.