yab_download: Tiny textpattern plugin to offer downloads

I wrote a tiny textpattern plugin for a customer of mine. It’s nothing spectacular, but if someone need it, feel free to download.

What it does

This plugin allows you to offer a download of multiple files (per file id and/or category) with or without a confirmation button. Additionally you can offer an option to download all the files as zip archive on the fly. The names of the files are read from the files description. If no description is given the filenames are displayed.

Usage

This plugin has only one tag: <txp:yab_download />. You have to place it in an individual article.
The following attributes are available:

  • files: The IDs of the files, which are for download (seperated by comma). If no files assigned with an ID an error message will displayed in the option field.
  • label1: Label for select
  • label2: Label for confirmation checkbox
  • label3: Label for the submit input
  • label4: Label for zip download checkbox
  • notice: Error notice, if confirmation is not set but required
  • size: Display filesize additionally (values are B, KB,MB, GB,PB).
  • confirm : Form used with a confirmation checkbox (values: ‚1‘ or some other string)
  • formid: html id of the element form, used for anchor, if you use more than one <txp:yab_download /> in a single site, make different entries here; (default yab_cd_download)
  • cats: File categories you will add to download (seperated by comma); will additional displayed with files from files attribute above
  • exclude: IDs of the files you will exclude; Does only work with cats attribute.
  • sort: Sort the files from cats; (defaul description asc)
  • zip: Offfers an checkbox with an option to download all offered files as zip instead (values: ‚1‘ for zip creation; ‚2‘ to force zip creation in memory)
  • zipname: the name of the offered zip (default all.zip)
  • hidelist: hides the select list of the files, usefull if you offer only one file or offer many files zipped without a seletion (values: ‚1‘)
  • hidezip: hides the zip checkbox (download as zip is forced), useful if you offer only one file as zip or many files as zip wihtout a file selection; can be combined with ‚hidelist‘, so only a download button will be displayed (values: ‚1‘)

Example usage

simple
<txp:yab_download files="1,2,3,4" />

full
<txp:yab_download files="1,2,3,4" label1="Choose your download" label2="Accept Download at your own risk" label3="Klick here for download" label4="Yeah give me all as zip" notice="You have to accept the condition below" size="MB" formid="form-no-1" confirm="1" cats="category1, category2" exclude="5,7" sort="filename desc" zip="1" zipname="archive.zip" />

The full example above will show you a form with two checkboxes. First one offers an option to download all the files zipped. The second checkbox is a confirmation checkbox.
The offered files will be the files with the file id #1, #2, #3, #4 and all files of the categories category1 and category2. If in category1 or category2 a file with the file id #5 and #7 so these will be excluded from download. The zipped file will be named as archive.zip.

Note on zip creation

If you are running a php version 5.2.0 or above so the attribute zip="1" will try to create the zip on harddisk instead in memory. If you have php 5.2.0 or above and you have problems with some restrictions like safe_mode, open_basedir etc., so try the attribute zip="2". This will force the zip creation in memory.

Download

This download of the plugin shows you a real world example.

If you have yab_confirmed_download v0.1 installed, disable or remove it, please! The plugin has been renamed.

Changelog

  • 08-11-23 – v0.1
    • release
  • 08-11-27 – v0.2
    • renamed the plugin to yab_download
    • added: confirmation is now optional
    • added: support files per categories
    • added: sort per category
    • added: files exclude
    • added: zip-on-the-fly
    • added: attribute formid for unique html ids for multiple plugin usage per page
  • 08-12-01 – v0.3
    • bugfix: filesize of category listing will now correctly calculated
    • bugfix: minor code improvement
  • 08-12-21 – v0.4
    • bugfix: code improvement (see comment below, thanks Geoffrey)
  • 09-01-08 – v0.5
    • bugfix: code improvement (see comment below, thanks Geoffrey); if a php 5.2.0 is running so zip creation will be on harddisk instead in memory
  • 09-11-16 – v0.6
    • bugfix: filenames and filedescriptions are now correctly escaped
    • added: new attribute ‚hidelist‘ hides the file selection list
    • added: new attribute ‚hidezip‘ hides the download-as-zip checkbox
  • 2017-02-10 – v0.7
    • TXP 4.6-ready

Kommentar

  1. # - Geoffrey Arnold schrieb am 21. Dezember 2008, 03:23:

    Great plugin! Thanks for your hard work!

    In our testing I noticed that using the zip function with large files may result in memory exhaustion causing a corrupt zip to be downloaded to the client. The issue is that each call to zipfile::file() returns a new copy of the zip in memory. Below is a diff of our fix, however a better fix would be if the zipfile class created the zip on disk instead of holding it in memory. The zip on disk could be streamed to the client by your plugin.

    Regards,
    Geoff.

    --- yab_download_v0.3.phps 2008-12-19 05:12:10.000000000 -0500
    +++ yab_download_v0.3_fix.phps 2008-12-20 20:36:16.000000000 -0500
    @@ -235,8 +235,7 @@
       header('Content-Type: application/zip');
       header('Content-Length: '.strlen($dump_buffer));
       header('Content-Disposition: attachment; filename = "'.$zipname.'"');
    -- strlen($dump_buffer);
    -- echo $zipfile->file();
    +  echo $dump_buffer;
       exit;
    }
    
  2. # - trenc schrieb am 21. Dezember 2008, 13:13:

    Oh, thanks Geoffrey.

    And I see the two lines were really … needless and redundant. I should not copy code from somewhere without re-adjusting to my needs. :/

    The variant with zip-creation on disk would be a better solution, but it would result in writing more code: So maybe in one of the next versions. ;)

  3. # - Geoffrey Arnold schrieb am 5. Januar 2009, 01:26:

    Here’s a modified version of the yab_zip_files() function which uses PHP’s native Zip extension to create the zip file on disk instead of in memory:

    function yab_zip_files($z_filenames_array, $zipname)
    {
      global $prefs;
      $path = $prefs['file_base_path'];
    
      // start new zipfile instance
      $tmpfile = tempnam('/tmp','zip');
      $zipfile = new ZipArchive();
    
      if ($zipfile->open($tmpfile,ZipArchive::OVERWRITE) === true)
      {
        // add every file from array to zipfile
        foreach ($z_filenames_array as $key => $val)
        {
          $z_filename = $path.'/'.$val;
          $zipfile->addFile($z_filename,$val);
        }
        $zipfile->close();
        @ob_end_clean();
        // create headers to force download
        header('Content-Type: application/zip');
        header('Content-Length: '.filesize($tmpfile));
        header('Content-Disposition: attachment; filename="'.$zipname.'"');
        readfile($tmpfile);
        @unlink($tmpfile);
        exit;
      }
    }
    
  4. # - trenc schrieb am 8. Januar 2009, 14:34:

    Hi Geoffrey,

    thanks for sharing. I’ve modified the your snippet so $tmpfile will be taken from txp-prefs and I included a fallback for php version minor than 5.2.0 (Implementation of ZipArchive).





Textile-Hilfe