tarmes
tarmes

Reputation: 15442

PHP script to deliver latest version of a file

My PHP's rusty and I'm hoping that someone can help me with a quick script - I don't really know where to start with it!

I have a folder containing zipped archives of various versions of a software product:

etc.

Now, on my web site I have a button to download the product. However, I'd like that button to always download the latest version.

It seems to me that a nice solution would be to link to a PHP script that would scan the folder for the latest version and deliver that file to the user as if they have pointed the browser directly at the file.

Can anyone provide me with a starting point?

Upvotes: 3

Views: 309

Answers (4)

Bart
Bart

Reputation: 17361

I think it's the easiest to read the files from the directory into an array. Then natsort the array and pop off the last entry.

Here is an example:

<?php
function getLatestVersion() {
    $dir = dir('.');
    $files = array();

    while (($file = $dir->read()) !== false) {
        $files[] = $file;
    }
    $dir->close();

    natsort($files);
    return array_pop($files);
}

Outputs

array(6) {
  [0]=>
  string(1) "."
  [1]=>
  string(2) ".."
  [2]=>
  string(16) "Product_1.00.zip"
  [3]=>
  string(16) "Product_1.05.zip"
  [5]=>
  string(16) "Product_2.00.zip"
  [4]=>
  string(17) "Product_10.00.zip"
}

How to download the latest version of the zip file?

EDIT

Like @j_mcnally pointed out in his comment below it's more efficient to let the webserver handle the serving of static files. Possible ways are direct links or redirecting the request from the PHP file to the right location using a 301.

But if you still want to let PHP do the work. Here is an example.


Grabbed the example below from http://perishablepress.com/http-headers-file-downloads and altered it a bit.

<?php // HTTP Headers for ZIP File Downloads
// http://perishablepress.com/press/2010/11/17/http-headers-file-downloads/

// set example variables

// Only this line is altered
$filename = getLatestVersion();

$filepath = "/var/www/domain/httpdocs/download/path/";

// http headers for zip downloads
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filepath.$filename));
ob_end_flush();
@readfile($filepath.$filename);
?>

Upvotes: 2

Eddie
Eddie

Reputation: 13116

This code works by using the file modification time to determine the latest version in the given directory, perhaps using regular expressions on the file names would be a better approach, however this demonstraits PHP's DirectoryIterator.

$files = array();

foreach(new DirectoryIterator("productZips/") as $fileInfo) {

  if(!$fileInfo->isFile()) continue;
  $files[$fileInfo->getMTime()] = $fileInfo->getFilename();
}

ksort($files);
$latestFile = array_pop($files);

You can read more here: http://php.net/manual/en/class.directoryiterator.php

Upvotes: 0

Minras
Minras

Reputation: 4346

This should work. Of course, more checks can be added depending on what else can be stored in that folder; you may also change the way of reading the folder content if it contains too many files, etc. Keyword in this code is probably strnatcmp() for strings comparison.

<?php
$files = scandir('/path/to/files');
$result = array_reduce(
    $files,
    function($a, $b) {
        $tpl = '/^Product_(.+).zip$/';
        // return second file name if the first file doesn't follow pattern Product_XXX.zip
        if (!preg_match($tpl, $a)) {
            return $b;
        }
        // return first file name if the second file doesn't follow pattern Product_XXX.zip
        if (!preg_match($tpl, $b)) {
            return $a;
        }
        return strnatcmp($a, $b) >= 0 ? $a : $b;
    },
    ''
);

Upvotes: 1

Dan Clarke
Dan Clarke

Reputation: 246

The below will look within the downloads directory, find the latest file (by looking at the modify time of the files) and return the name of the newest file:

$dir = dir("downloads");
$files = array();
while (($file = $dir->read()) !== false) {
    $files[filemtime($file)] = $file;
}
$dir->close();

ksort($files);
$fileToDownload = $files[0];

Hope this helps!

Upvotes: 0

Related Questions