PHP help needed for downloading files

How do I download a file based on it's ID? Right now I have an upload script that timestamps all files as they reach the server. I can't use the $_FILES[file]['name'] global to retrieve the files by name since they're all uniquely named.

Here's what my upload code looks like:

$targetPath = dirname( __FILE__ ) . DIRECTORY_SEPARATOR . $upload_dir . DIRECTORY_SEPARATOR;
// Adding timestamp with image's name so that files with same name can be uploaded easily.
$mainFile = $targetPath.date("Y-m-d H-i-s").'-'. $_FILES['file']['name'];
//get variables for database			
$projectname=$_POST['projectname'];
$version= $_POST['version'];					
$comments=$_POST['comments'];

if(move_uploaded_file($tempFile,$mainFile)){
	include 'db.php';
	$add = mysql_query("INSERT INTO `myversions`(filename, filetype, projectname, version, comments, created) 
	VALUES ('$FileName', '$file_type','$projectname','$version','$comments', NOW())"); 		
echo "Your file ".  basename( $_FILES['file']['name']). " has been successfully uploaded and recorded in the database!";
 	}	
	else {
		echo "Your file failed to upload.";
	}	
}

Here's what the view code looks like. As you can see the download link is just a blank HREF right now.

Error_Reporting(0);
	include("db.php");

	//Show all files
	$result = mysql_query("SELECT * FROM myversions ORDER by projectname ASC, created DESC");

	echo "<div class='table-responsive'>";
			echo "<table class='table table-striped table-bordered'>";
			echo "<thead>";
			echo "<tr>";
			echo "<th>File Name</th><th>Project Name</th><th>Version</th><th>Comments</th><th>Created</th>";
			echo "</tr></thead>";
			echo "<tbody>";  
		
	while($row = mysql_fetch_array($result)){
		$id = $row['id'];	
			echo "
			<tr>
			<td>$row[filename]</td>
			<td>$row[projectname]</td>
			<td>$row[version]</td>
			<td>$row[comments]</td>
			<td>$row[created]</td>
			<td><a href='#'>Download File</a></td>
			</tr>";  		
	}

	echo "</tbody>"; 
	echo "</table>";
	echo "</div>"; 

	//close connection
	mysql_close($conn);

I know I should do something like:

$id = $row['id'];

and pass it like:

<a href ='download.php?id=$id'>Download</a>

Not sure how to finish it off though.

Change:

// Adding timestamp with image's name so that files with same name can be uploaded easily.
$mainFile = $targetPath.date("Y-m-d H-i-s").'-'. $_FILES['file']['name'];

To:

// Adding timestamp with image's name so that files with same name can be uploaded easily.
$tiem = date("Y-m-d H:i:s",time());
$mainFile = $targetPath.$tiem.'-'. $_FILES['file']['name'];

And Change:

$add = mysql_query("INSERT INTO `myversions`(filename, filetype, projectname, version, comments, created) 
	VALUES ('$FileName', '$file_type','$projectname','$version','$comments', NOW())");

To:

$add = mysql_query("INSERT INTO `myversions`(filename, filetype, projectname, version, comments, created) 
	VALUES ('$FileName', '$file_type','$projectname','$version','$comments', '$tiem)");

Then on the upload portion:

		<td><a href='" . $result['created'] . rawurlencode($result['filename']) . "'>Download File</a></td>

Also, I get that your skipping out on bits of your code for simplicity sake, but in the long term it's more confusing than anything else. Case in point:

created) 	VALUES ('$FileName',

Where did $Filename come from? Even cutting bits of code out that looks like your storing nothing where the filename should go.

I've made changes to the code. I'm getting closer to a fully working thing. What I want to do is use this as a primitive version control for my scripts in lieu of Git or Subversion. I don't have need for their advanced functionality.

Basically, when the user selects "Minor" from a HTML selectbox I want the filename to increment by 0.1 such that it would be something like: filename_Ver 0.1" and increment by 1 if they select "Major". In this way, I could mix and match to get something like filename_Ver 1.2. The only thing that's not working is the minor section of the code. My while loop becomes an infinite loop whenever I upload a file with the same name more than once. Not sure why.

if ( isset( $_POST['addfile'] ) ) {

// variables
 define('UPLOAD_DIR', 'repository/'); 
 $fileName = $_FILES['fileToUpload'];

if($_POST['rev_type'] == 'Minor') {

function update_file_name_minor($file) 
{
  $pos = strrpos($file,'.');
  $ext = substr($file,$pos); 
  $dir = strrpos($file,'/');
  $dr  = substr($file,0,($dir+1)); 

  $arr = explode('/',$file);
  $fName = substr($arr[(count($arr) - 1)], 0, -strlen($ext));

  $exist = FALSE;
  $i = 0.01;

  while(!$exist)
  {
    $file = $dr.$fName.'_'.'Ver '.$i.$ext;

    if(!file_exists($file))
      $exist = TRUE;

    $i + 0.01;
  }

  return $file;
}

// check for which action should be taken if file already exist
if(file_exists(UPLOAD_DIR . $fileName['name'])) 
{
  $updatedFileName = update_file_name_minor(UPLOAD_DIR.$fileName['name']);
  move_uploaded_file($fileName['tmp_name'], $updatedFileName);

  echo "You have successfully uploaded and renamed the file as a minor revision.";
}
else
{
  move_uploaded_file($fileName['tmp_name'], UPLOAD_DIR.$fileName['name']);

 echo "You have successfully uploaded the file.";
}

}

elseif($POST['revtype'] == 'Major') {

function update_file_name_major($file) 
{
  $pos = strrpos($file,'.');
  $ext = substr($file,$pos); 
  $dir = strrpos($file,'/');
  $dr  = substr($file,0,($dir+1)); 

  $arr = explode('/',$file);
  $fName = substr($arr[(count($arr) - 1)], 0, -strlen($ext));

  $exist = FALSE;
  $i = 2;

  while(!$exist)
  {
    $file = $dr.$fName.'_'.'Ver '.$i.$ext;

    if(!file_exists($file))
      $exist = TRUE;

    $i++;
  }

  return $file;
}

// check for which action should be taken if file already exist
if(file_exists(UPLOAD_DIR . $fileName['name'])) 
{
  $updatedFileName = update_file_name_major(UPLOAD_DIR.$fileName['name']);
  move_uploaded_file($fileName['tmp_name'], $updatedFileName);

  echo "You have successfully uploaded and renamed the file as a major revision.";
}
else
{
  move_uploaded_file($fileName['tmp_name'], UPLOAD_DIR.$fileName['name']);

 echo "You have successfully uploaded the file.";
     }           
  }         
} //main if

Should be:

$ext = end(explode(".",$file));

Which should stop the never ending loop.

EDIT: Also... your $fName looks off.

The infinite loop still continues. What looks wrong with $fName? It looks like it's extracting the right info.

$dr ... unless your server is on / (In *nix) or D:\ (In Windows doesn't make sense. As there would be mutliple directories in between the start of the file system and whatever directory your working out of.

So $dr should be something like:

$dr = str_replace(end(explode("/",$file)), '', $file);

In order to get the full directory path. Because in the loop it's check for something in the wrong directory. $fName looks weird because you're not subtracting $dr from $file... so there's room for inconsistencies in file location.

Also, $fName can be done in:

$fName = current(explode(".",end(explode("/",$file)));

I think I've narrowed down the infinite loop issue to relating to the $FName because $i is saved as a double. I tried your code $fName = current(explode(".",end(explode("/",$file))); but it returns a syntax error, saying the ';' is unexpected. I can't spot the error.

By the way, the test environment is on a Mac running XAMP.

That's my bad... that should've been:

$fName = current(explode(".",end(explode("/",$file))));

I forgot the last ")".

Damn it still times out. I don't know what could be causing this. Here's the entire code if you want to take a stab:

Code Download

Line 31 of upload.php:

    $i + 0.01;

Doesn't increment anything. Try:

    $i += 0.01;

That seems to have done the trick man! Thanks.

EDIT: Now I need to find a way to combine the two so that if a file was for example, Version 1 and I uploaded a minor revision to it it would tack on 0.1, add another minor version, 0.2, etc. Thus, the end result would look like filename_Ver 1.2 at the end of the changes.