3

I have discovered that HTTP PUT Request ist the most suitable for very large files upload (1GB or more).

The solution works well and I can upload any file of my choice to the server. However, I have difficulties monitoring upload progress.

I have implemented onprogress callback, but this one gets called only once after the file is uploaded via PUT.

My JavaScript Code:

var req = createRequest();
req.open("PUT", "PHP/upload_file.php?folder=" + aUploadedFile.upload_folder + "&master_folder=" + settings.strServerSideMasterFolder + "&file_name=" + aUploadedFile.file_name);
req.setRequestHeader("Content-type", "text/plain");
req.onload = function (event)
{
    console.log("OnLoad Called: " + aUploadedFile.file_name);
}
req.onprogress = function (event)
{
    console.log("OnProgress Called: " + aUploadedFile.file_name);
}
req.send(aUploadedFile.file_object);
  • What are my options when i wish to monitor the upload progress via PUT, please?
  • Should I establish another JavaScript AJAX call, that will monitor the size of the uploaded file o the server?
  • Is there any other working solution available?

I use:

  • HTML5
  • JavaScript
  • PHP
  • Apache

I do not use:

  • jQuery

Thank you in advance.

Bunkai.Satori
  • 4,698
  • 13
  • 49
  • 77
  • Have you seen this? http://stackoverflow.com/questions/49564/how-to-implement-file-upload-progress-bar-on-web – John Zwinck Mar 02 '13 at 12:54
  • 1
    @JohnZwinck: Hi. Thanks for the comment. My question is probably very specific? Your link shows various implementations of progress bar but none of them is related to HTTP PUT Request. It is fairly simple to create progress bar for HTTP POST Requests, but problem is that the **same code does not work for HTTP PUT Requests**. – Bunkai.Satori Mar 02 '13 at 13:00
  • Why do you eschew POST? – John Zwinck Mar 02 '13 at 13:57
  • 1
    @JohnZwinck: File Upload using HTTP POST Requests is in my opinion easier, and provides easy implementation of upload progress. **However**, POST Requests place the whole uploaded file into server's memory for a while. If more people upload their files, there is risk of consuming all the server's memory. On top of that, there were difficulties, that I could not upload more than 300MB, because the client thought, the upload process is frozen, and displayed: "Aw, Snap!" I tried every possibility I had found on the internet, but I did not find suitable POST Request solution. – Bunkai.Satori Mar 02 '13 at 14:14

1 Answers1

4

Have you tried xhr.upload.onprogress instead of xhr.onprogress?

If that doesn't work too, you could establish another JavaScript AJAX call, like you said. Recently, I've made an upload system that read the file line per line, and it needed to show some extra information about the upload, and not just the percentage, so I did something like this:

  • The main page makes an AJAX request to a file responsible to process the file
  • In that file, I had to close the connection, so the AJAX request could complete, but the PHP script would still be running, using this:
ob_start();
$file = tempnam('/tmp', uniqid()); // create a temp file to show status of the action
echo json_encode(array('file' => $file));
header('Content-length: '.ob_get_length());
header('Connection: close');
ob_end_flush();
flush(); // The AJAX request is completed here, but the script is still running...

function writeToFile($handle, $arr) {
    ftruncate($handle, 0); // empty file
    fwrite($handle, json_encode($arr));
}
$handle = fopen($file, 'w');
while (readLine($uploadedFile)) {
    // code to process line
    writeToFile($handle, array('progress' => $current / $total, 'action' => 'Reading...'));
}
// insert into database
writeToFile($handle, array('progress' => '100', 'action' => 'Inserting into database...'));
fclose($handle);
  • At the main page, the AJAX request would return the name of the file that contains the information, so I would create several GET requests to that file, using setInterval method

Note: in my case, I created another PHP file to show the contents of the progress file (with file_get_contents), so I could manually delete that file when the operation completes

vcampitelli
  • 3,168
  • 1
  • 12
  • 13
  • 2
    Hi, +1 and thanks for your response. What you write makes perfect sense. To answer your question, no, I haven't tried `xhr.upload.onprogress` but I will give it a try. Meanwhile, I was able to implement the progress bar with additional AJAX calls. I do not like, that for every progress bar, I have to issue several, even hundreds of AJAX calls. I therefore study subjects like COMET and AJAX Long Polling, which establish one permanent connection between the server and the client, and can more precisely update the progress bar. I'm studying it now, so I will see if it is applicable. – Bunkai.Satori Mar 02 '13 at 14:23
  • 3
    I have to tell you, that i've just tried `xhr.upload.onprogress` instead of `xhr.onprogress` and it made all the difference. `xhr.upload.onprogress` **works just great**. Although I do not understand the difference, I thank you very much for this great tip, and I am marking your answer as the *Acceptable Answer* to my question. Thank you again! – Bunkai.Satori Mar 02 '13 at 14:36
  • Interesting solution. – The Onin Apr 25 '17 at 05:10