ZIP direct download of current node filefield

Add a node menu local task that will create a temporary ZIP file on-the-fly containing files from a file field.
All files of a filefield identified by the field name (defaults to: field_download) will be added to it.
Force a download by the user's browser.

* Implementation of hook_menu
function onlinepdf_menu() {
$items['node/%node/zip'] = array(
'title' => 'Download as ZIP',
'page callback' => 'onlinepdf_zip',
'access callback' => TRUE,
'type' => MENU_LOCAL_TASK,
return $items;

* Page callback
* function: force a zip file to download generated on the fly with files from current node filefield
* arguments: filefield name (defaults to field_download)
function onlinepdf_zip($filefield = 'field_download') {
//loads node object from current path
$node = menu_get_object("node", 1, current_path());
//check if the filefield exists and contains file records
if (isset($node->{$filefield}) && isset($node->{$filefield}[LANGUAGE_NONE]) > 0)
//create zip archive and add the files to it
$zip = new ZipArchive();
$uri = 'public://zip/'.mt_rand().'.zip';
$filepath = drupal_realpath($uri);
$filename = basename($filepath);
//could not create zip file, throw error and 404
if ($zip->open($filepath, ZipArchive::CREATE)!==TRUE) {
drupal_set_message(t('Could not open %filename', array('%filename' => $filename)), 'error');
watchdog("onlinepdf", 'Could not open %filename', array('%filename' => $filename), WATCHDOG_ERROR);
foreach ($node->field_download[LANGUAGE_NONE] as $file)
if (!$zip->addFile(drupal_realpath($file['uri']), $file['filename']))
//error in adding file to zip. throw error, discard zip and give 404
drupal_set_message(t('Could not add %filename to zip archive', array('%filename' => $file['filename'])), 'error');
watchdog("onlinepdf", 'Could not add %filename to zip archive', array('%filename' => $filename), WATCHDOG_ERROR);
return drupal_not_found();
//create file object from zip file
$file = new stdClass;
$file->filename = $filename;
$file->uri = $uri;
$file->filemime = file_get_mimetype($uri);
$file->filesize = filesize($filepath);
//set file as temporary. Will be deleted after 6 hours by cron
$file->status = 0;
$file = file_save($file);
file_transfer($file->uri, array('Content-disposition' => 'attachment; filename='.$filename));
else {
//no filefield with file records found, throw 404
return drupal_not_found();