Problem/Motivation

Most popular operating systems (Windows and macOS) don't extract tar.gz compressed files by default (as far as I am concerned). Some clients have asked us if it would be possible to, when downloading uploaded files from webform results, have a file compressed as a ZIP instead.

Proposed resolution

Add functionality to provide user the ability to choose tar.gz or zip as type of compressed file for results' uploaded files.

User interface changes

In terms of user interface, I believe that, when user checks the checkbox "Download uploaded files", a pair of radio buttons should show up asking what type of compressed file to be used, tar.gz or zip.

Thank you.

Mauricio

Comments

maursilveira created an issue. See original summary.

jrockowitz’s picture

I think this might be possible because Drupal core does support zip files but it is going to require some major refactoring.

The webform module's exporter is hardcoded to manipulate only Tar files. The code was written several years ago and I was probably not able to get Zip archiving working at the time.

jrockowitz’s picture

So Drupal's support for ZIP and even TAR is not great.

I decided to write the below code snippet that shows how to create the needed ZIP or TAR archive for webform submissions export.

The next step would be to refactor the \Drupal\webform\WebformSubmissionExporter to use a custom service or helper that supports creating TAR and ZIP archives.

/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system');

$test_files_directory = DRUPAL_ROOT . '/' . drupal_get_path('module', 'webform') . '/tests/files';
$test_file = $test_files_directory . '/sample.jpg';
$archive_extensions = ['tar.gz', 'zip'];

foreach ($archive_extensions as $archive_extension) {
  $archive_filepath = file_directory_temp() . '/webform.archiver.test.'  . $archive_extension;
  if (file_exists($archive_filepath)) {
    $file_system->delete($archive_filepath );
  }

  switch ($archive_extension) {
    case 'tar.gz':
      // Create TAR archive.
      $archive = new ArchiveTar($archive_filepath);
      $archive->_compress = TRUE;
      $archive->_compress_type = 'gz';

      // Write sample.jpg file to root.
      $archive->addModify($test_file, '', $test_files_directory);

      // Write sample.jpg file to custom-directory root.
      $archive->addModify($test_file, 'custom-directory', $test_files_directory);

      // Write a custom string of text to a test.txt file.
      $archive->addString('test.txt', 'This is a test.');

      // Write a directory to root.
      $archive->addModify($test_files_directory, 'files', $test_files_directory);

      // Write a custom directory.
      $archive->addModify($test_files_directory, 'custom-files', $test_files_directory);

      // Get archived files.
      $files = [];
      foreach ($archive->listContent() as $file_data) {
        $files[] = $file_data['filename'];
      }
      print '<h3>' . $archive_filepath . '</h3>';
      print '<pre>'; print_r($files); print '</pre>'; 
      break;

    case 'zip':
      // Create ZIP archive.
      $archive = new \ZipArchive();
      $archive->open($archive_filepath, \ZipArchive::OVERWRITE | \ZipArchive::CREATE);

      // Write sample.jpg file to root.
      $archive->addFile($test_file, 'sample.jpg');

      // Write sample.jpg file to custom-directory root.
      $archive->addFile($test_file, 'custom-directory/sample.jpg');

      // Write a custom string of text to a test.txt file.
      $archive->addFromString('test.txt', 'This is a test.');

      // Write a directory to root.
      $options = array('add_path' => 'files/', 'remove_path' => $test_files_directory);
      $archive->addPattern('/\.[a-z0-9]+$/', $test_files_directory, $options);

      // Write a custom directory.
      $options = array('add_path' => 'custom-files/', 'remove_path' => $test_files_directory);
      $archive->addPattern('/\.[a-z0-9]+$/', $test_files_directory, $options);

      // Get archived files.
      $files = [];
      for ($i = 0; $i < $archive->numFiles; $i++) {
        $files[] = $archive->getNameIndex($i);
      }
      print '<h3>' . $archive_filepath . '</h3>';
      print '<pre>'; print_r($files); print '</pre>'; 
      break;
  }
}
jrockowitz’s picture

I think below are the four helper methods that need to be added to the WebformExporterInterface.

\Drupal\webform\Plugin\WebformExporterBase::getArchive();
\Drupal\webform\Plugin\WebformExporterBase::addArchiveDirectory($directory, $name, $remove_path);
\Drupal\webform\Plugin\WebformExporterBase::addArchiveFile($file, $name, $remove_path);
\Drupal\webform\Plugin\WebformExporterBase::addArchiveString($text, $name);

  • 58b02ef committed on 3111819-zip
    Issue #3111819: Download results uploaded files as ZIP. Refactor export...
jrockowitz’s picture

Status: Active » Needs review
StatusFileSize
new15.31 KB

The attached patch refactors the webform exporter's archive support to make it possible to support ZIP archives.

Next steps

  • Add archive_type (tar or zip) to exporter configuration setting
  • Change archive extension based on archive type
  • Make sure ZIP support is only available when ZipArchive is installed.
  • Update webform submission export drush command.
  • Update tests to generate TAR and ZIP file.

  • f4fc483 committed on 3111819-zip
    Issue #3111819: Download results uploaded files as ZIP. Add ZIP support...

  • 8bbe96d committed on 3111819-zip
    Issue #3111819: Download results uploaded files as ZIP. Automated test...
jrockowitz’s picture

StatusFileSize
new33.77 KB

If all the tests pass, this patch can be reviewed.

Status: Needs review » Needs work

The last submitted patch, 9: 3111819-9.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

  • 3ec106f committed on 3111819-zip
    Issue #3111819: Download results uploaded files as ZIP. Automated test...
jrockowitz’s picture

Status: Needs work » Needs review
StatusFileSize
new33.75 KB

  • 6b7c11e committed on 3111819-zip
    Issue #3111819: Download results uploaded files as ZIP. Minor copy tweak...

Status: Needs review » Needs work

The last submitted patch, 12: 3111819-12.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

  • c714352 committed on 3111819-zip
    Issue #3111819: Download results uploaded files as ZIP. Minor copy tweak...
jrockowitz’s picture

Status: Needs work » Needs review
StatusFileSize
new47.62 KB

  • 19d6153 committed on 3111819-zip
    Issue #3111819 by jrockowitz: Download results uploaded files as ZIP....
jrockowitz’s picture

StatusFileSize
new47.92 KB
jrockowitz’s picture

StatusFileSize
new4.29 KB

Below are my steps for manually testing this change.

  • Install the attached webform
  • Generate 50 submissions - /webform/issue_3111819/test
  • Download results as CSV - /admin/structure/webform/manage/issue_3111819/results/download
  • Download results as CSV with files in Tar
  • Download results as CSV with files in ZIP
  • Download results as PDF in Tar
  • Download results as PDF in ZIP

  • jrockowitz authored 61c3e2d on 8.x-5.x
    Issue #3111819 by jrockowitz: Download results uploaded files as ZIP
    
jrockowitz’s picture

Status: Needs review » Fixed

I committed the patch. Please download the latest dev release to review.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

mogio_hh’s picture

Sorry to be a pain. Could somebody guide me to the exact location where I could set, that users have the option to download the uploaded files of a submission as an archive?
I could not find it in the settings. Also I am a little bit confused we talk here about downloading all submissions instead of the uploaded files of 1 submission. Wasn't the issue poster asking for "uploaded files". Misunderstanding on my side?

jrockowitz’s picture

StatusFileSize
new145.53 KB
The Webform module's issue queue is for bugs, feature requests, and planning. Please post general support questions to Drupal Answers. You can also ask questions or help answer questions on the #webform channel on Drupal Slack.

mogio_hh’s picture

Thank you!
Still not what I expected. Is it possible to create a zip + download link for the uploaded files of a webform submission, instead of having the client to download each file individuell?

In a perfect world the generated email with the data of the submission would provide the url to the zip. So clients don't have to download the files one by one.

Was this ever planed or is it necessary to patch webform?

jrockowitz’s picture

Providing a zip of uploaded files would need to be handled via custom code or a dedicated contrib module.

Monster971’s picture

Hello,
I am interested in the subject but I did not really understand.
Indeed I wish to be able to offer the possibility of downloading the files submitted by webform in a zip file via a link in a view in a table?
Is it possible to achieve this?

srdtwc’s picture

StatusFileSize
new50.71 KB

I noticed that the UI has the option to select tar.gz or zip, but when you selection zip nothing seems to happen. No errors are displayed. Is this intended functionality?

UI screenshot