How to append .part to partial upload files (php)
Posted: Fri Oct 08, 2010 2:58 pm
So I've been using your demo copy of JFileUpload to see if it will work with what we need (a way for our customers to upload large files (>2GB) to our server). After tweaking a few things, playing with settings and writing a new html page (in php) everything looked good. I did find one issue during testing however.
Uploading files in chunks using "onflyrange" was working great for large files and resuming uploads. HOWEVER, as the file was being uploaded and the chunks were being added to the file, the file looked complete from the admin end (the file showed no indication that it wasn't fully uploaded).
I've created a solution, by appending ".part" to the end of files being transferred in this way. After the last chunk is added, the file is renamed to take off the ".part". This eliminates confusion and allows admins to easily see if a file is complete without having to download a local copy first.
I've included my code, because I felt like this could be a good addition to a future version of the sample scripts, or to help anyone out that wants this feature. If I were to get a free license from this contribution though, I sure wouldn't mind
First, change the checking for pre-existing files to include the .part
Then, update the resume code to use the .part file and rename it when done. This is from the 'post' resume.
Finally, edit the code to make the first uploaded chunk a .part file.
Happy coding!
-Jason
jblount (at) ecrsoft (dot) com
Uploading files in chunks using "onflyrange" was working great for large files and resuming uploads. HOWEVER, as the file was being uploaded and the chunks were being added to the file, the file looked complete from the admin end (the file showed no indication that it wasn't fully uploaded).
I've created a solution, by appending ".part" to the end of files being transferred in this way. After the last chunk is added, the file is renamed to take off the ".part". This eliminates confusion and allows admins to easily see if a file is complete without having to download a local copy first.
I've included my code, because I felt like this could be a good addition to a future version of the sample scripts, or to help anyone out that wants this feature. If I were to get a free license from this contribution though, I sure wouldn't mind
First, change the checking for pre-existing files to include the .part
Code: Select all
$fpart = $fhead . ".part";
if (file_exists($fhead) && !(file_exists($fpart)))
{
header("size: ".filesize($fhead));
if ($debug) fwrite($lg," Previously uploaded file found: ".$fhead."\r\n");
}
elseif (file_exists($fpart)){
header("size: ".filesize($fpart));
if ($debug) fwrite($lg," .part file found: ".$fpart."\r\n");
}
else{
if ($debug) fwrite($lg," No file found"."\r\n");
header("HTTP/1.1 404");
}Code: Select all
$file_path_part = $file_path . ".part";
$isPart = (file_exists($file_path_part))?true:false;
$result = FALSE;
if (($resume_enabled == "true") && ($isPart) && (isset($_SERVER['HTTP_CONTENT_RANGE'])))
{
// Resume support.
$range_header = $_SERVER['HTTP_CONTENT_RANGE'];
if (substr($range_header,0,6) == 'bytes ')
{
$minus = strpos($range_header,'-');
$start_offset = substr($range_header,6,$minus-6);
$file_path_tmp = $file_path.".".$start_offset.".".time();
if ($debug) fwrite($lg," move_uploaded_file:".$temp_name." to ".$file_path_tmp."\r\n");
$result = move_uploaded_file($temp_name, $file_path_tmp);
if ($debug) fwrite($lg," move_uploaded_file:".$result."\r\n");
if ($debug) fwrite($lg," Resuming at offset ".$start_offset." with ".$file_path_tmp."\r\n");
$fout = fopen ($file_path_part, "rb+");
if ($debug) fwrite($lg," Writing to: ".$file_path_part."\r\n");
$seekedit = fseek ($fout,$start_offset);
$fin = fopen ($file_path_tmp, "rb");
while (!feof($fin))
{
$read = fread($fin,8192);
fwrite($fout,$read);
}
fclose($fin);
if ($debug) fwrite($lg," Deleting:".$file_path_tmp."\r\n");
unlink($file_path_tmp);
fclose($fout);
if ($debug) fwrite($lg," Resume completed"."\r\n");
if ($_POST["chunkbasesize"] == ($_POST["chunkonflysize"] + $_POST["chunkonflyoffset"])){
//This is the last chunk
if ($debug) fwrite($lg,"Renaming from .part name to complete name: ");
if (file_exists($file_path)) unlink($file_path);
if (rename($file_path_part, $file_path)){
if ($debug) fwrite($lg,"Success"."\r\n");
}else{
if ($debug) fwrite($lg,"Failure"."\r\n");
}
}
}
else
{
if ($debug) fwrite($lg," Cannot resume:".$range_header."\r\n");
}
}Code: Select all
if (($_POST["chunkbasesize"] > $_POST["chunkonflysize"]) && ($_POST["chunkonflyoffset"] == 0)){
//first chunk, need to upload as .part
if ($debug) fwrite($lg," This is the first chunk of a multipart upload"."\r\n");
if ($debug) fwrite($lg," move_uploaded_file:".$temp_name." to ".$file_path_part."\r\n");
$isPart = true;
$result = move_uploaded_file($temp_name, $file_path_part);
}
else{
//reg upload, only part
if ($debug) fwrite($lg," move_uploaded_file:".$temp_name." to ".$file_path."\r\n");
$result = move_uploaded_file($temp_name, $file_path);
}
if ($debug) fwrite($lg," move_uploaded_file:".$result."\r\n");
}
if ($result)
{
chmod($file_path,0755);
$message = ($isPart)?"$file_name uploaded successfully.":"$file_name.part uploaded successfully.";
return $message;
}
-Jason
jblount (at) ecrsoft (dot) com