Abdulmanan Abdulmanan - 1 month ago 13
PHP Question

how to add a progress bar to script that downloads file from url to server

I have searched for a script that download files from url to server and i came across this script. it works fine but i want to add some things to it like multi urls and progress bar .as i am new in php i know a little .

here is the script in which i want to implement:



<html>
<form method="post">
<input name="url" size="50" />
<input name="submit" type="submit" />
</form>
<?php
// maximum execution time in seconds
set_time_limit (24 * 60 * 60);

if (!isset($_POST['submit'])) die();

// folder to save downloaded files to. must end with slash
$destination_folder = 'downloads/';

$url = $_POST['url'];
$newfname = $destination_folder . basename($url);

$file = fopen ($url, "rb");
if ($file) {
$newf = fopen ($newfname, "wb");

if ($newf)
while(!feof($file)) {
fwrite($newf, fread($file, 1024 * 8 ), 1024 * 8 );
}
}

if ($file) {
fclose($file);
}

if ($newf) {
fclose($newf);
}
?>
</html>




Answer

Since you want to have the ability to show new input boxes here is the code:

<html>

<form method="post">
<input type="text" id="input1" name="input1" size="50" />
<div id="new"></div>
<br><input type="button" value="+" onclick="writeBtn();"><br><br>
<input name="submit" value="Download" type="submit" />
</form>

<script type="text/javascript">

url_id=1;

function writeBtn()
{
    if (document.getElementById("input"+url_id).value != "")
    {
        url_id++;
        var input = document.createElement("input");
        input.type="text";
        input.id="input"+url_id;
        input.name="input"+url_id;
        input.size="50";
        input.required=true;
        var br1 = document.createElement("br");
        var br2 = document.createElement("br");
        setTimeout(function(){
            $(input).click();
        },200);

        document.getElementById('new').appendChild(br1);
        document.getElementById('new').appendChild(input);
        document.getElementById('new').appendChild(br2);
    }
    else
    {
        alert("Please complete the last url first.");
    }
}

</script>


<?php 
    // i have just added this maximum execution time in seconds
    set_time_limit (0);
function downloadFromUrl($url, $destination)
{
    $newfname = $destination . basename($url);

    $file = @fopen ($url, "rb");
    if ($file)
    {
        $newf = fopen ($newfname, "wb");

        if ($newf)
            while(!feof($file)) 
            {
                fwrite($newf, fread($file, 1024 * 8 ), 1024 * 8 );
            }
			// and replaced this with if command
			if ($file) {

			fclose($file);
}
    if ($newf) {
      fclose($newf);
    }
        return true;
    }
    else
    {
        return false;
    }

}

if (!isset($_POST['submit'])) die();

// folder to save downloaded files to. must end with slash
$destination_folder = 'downloads/';

for ($i=1; isset($_POST["input".$i]); $i++)
{      
    $url = $_POST["input".$i];

    if(downloadFromUrl($url, $destination_folder))
        echo "<br>Succesfully Downloaded from: ".$url;  
    else            
        echo "<br>Error Downloading from: ".$url;   

}

?>

Explanation:

In the html form there is a div with id="new". In this div is where an input box is dynamically added when the button with the + sign is clicked. If you want to learn more about how this is achieved you can visit this link: http://www.w3schools.com/jsref/met_document_createelement.asp. The values from input boxes are afetrwards accessed by their names, which are input1, input2 etc. For this dynamic name giving the variable url_id is used in javascript part and is increased for every new input box. Also there is a feature I added, which doesn't allow user to create new input if the last one is empty and alerts a message. The if statement for this is:

if (document.getElementById("input"+url_id).value != "")

so, if you don't want this just delete this line and the else block. I also included your code for downloading in the function downloadFromUrl for simplicity reasons, which returns true if file was succesfully downloaded and false otherwise. In the php part there is a for loop that parses all inputs downloads the file that is in the url and echos a message if it was or not succesfully downloaded by calling the function downloadFromUrl.

As for your other question about the progress bar, I spent like the whole day trying to find a solution. Long story short, I wasn't able to make it work and I think it can't possibly work. I will explain you why. From php we can't change the value of the progress bar because php is executed and then prints all the results on screen, so we will only have the last change of the progress bar which will always be 100%. The other way is to use javascript. In that case we have to download the files from javascript because if we download them from php, by the time javascript starts executing, the files will have already been downloaded from php. Even if we execute a php script from javascript that downloads the files , we won't be able to tell when a file is downloaded, so we can't update the progress bar at the right time. So what is left? Downloading the files from javascript using XMLHttpRequest, which can't be achieved for 2 reasons. First, browsers don't allow this for security reasons and second and most important you can't upload the file to the server from javascript because javascript is a client-side language and doesn't have access to the server.

As you can see I tried many ways. If someone finds a way to do this, please let me know. I hope I helped you with your project. For any questions, problems, errors on the first half of the answer and suggestions or corrections for the second part of the answer are very welcome.