How to append .part to partial upload files (php)

Upload core product.
Post Reply
ecrs
Posts: 3
Joined: Thu Oct 07, 2010 3:10 pm

How to append .part to partial upload files (php)

Post by ecrs »

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 ;) :lol:

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");
    }
Then, update the resume code to use the .part file and rename it when done. This is from the 'post' resume.

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");
       }

    }
Finally, edit the code to make the first uploaded chunk a .part file.

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;
    }
Happy coding! :D

-Jason
jblount (at) ecrsoft (dot) com

User avatar
support
Posts: 1503
Joined: Sun Jan 27, 2008 6:19 pm

Re: How to append .part to partial upload files (php)

Post by support »

Thanks for the code sample.

Post Reply