简体   繁体   中英

Download file using php script, one at time

This is question about downloading files from server using php script. When user clicks on download link, it processed to download.php file, and using header it started downloading.

After downloading file there is one function in download.php file, which updates mysql database about file downloaded and deduct money from user's account. Everything works fine.

Now, the problem occurs when user have download manager installed in pc. Sometimes download started in browser and download manager both. So, at the end there are two download entries in database, And money deducted from user's account two times.

Question : Is there any way to start only one download at time? Or any other way to do this thing?

Download link I provide to user.

<a href='download.php?id=1'>Download Test Video</a>

The script I am using for downloading file. (download.php)

    $file = "c:/test.avi"; // $file = $_GET['id'];
    $title = "Test Video";

    header("Pragma: public");
    header('Content-disposition: attachment; filename='.$title);
    header("Content-type: ".mime_content_type($file));
    header("Content-Length: " . filesize($file) ."; ");
    header('Content-Transfer-Encoding: binary');
    ob_clean();
    flush();

    $chunksize = 1 * (1024 * 1024); // how many bytes per chunk
    if (filesize($file) > $chunksize) {
        $handle = fopen($file, 'rb');
        $buffer = '';

        while (!feof($handle)) {
            $buffer = fread($handle, $chunksize);
            echo $buffer;
            ob_flush();
            flush();
        }

        fclose($handle);
    } else {
        readfile($file);
    }

    record_download('user id', 'file id');

Moving the comment down here for anyone interested.

The function that I had to come up with was a unique download link after a payment had been processed. These are the steps that were taken.

  • Process the Payment and capture IP address, file and path of the downloadable file - save this information to the database.
  • Once payment has been deducted successfully, trigger a function that generates a unique token, eg: sha1(microtime().$transactionid) , and save this to the database (note: please don't use microtime() in production, use a random string generator).
  • Using .htaccess we generated a download link, eg: http://domain.com/download/<token> the .htaccess contents:

     RewriteRule ^download/([a-z0-9-]) /download.php?token=$1 
  • Optional : If their IP matches what we have in the database, go ahead and allow the user to download the file. If it doesn't, we ask the user to log in so we can update their IP address and begin downloading.
  • Once you have the token, you can pretty much do any form of validation you would like from here, such as preventing multiple downloads by adding a column in the database download_downloaded INT(1) DEFAULT 0 where if it is set to 1, then it has been downloaded. I would suggest giving the user about a day before locking them out after downloading, just in case their file was corrupt in the process.
  • Any other additional items, such as download counter etc.
  • Finally use your code above after to start the download. I would have it structured a little differently though.

download.php

$token = $_GET['token'];
$allow_download = FALSE; // Can never be too careful..

...
//Database lookup to get the file ID
...

$file = "c:/test.avi"; // now from the database call
$title = "Test Video";

// Do any additional validation here
// returns TRUE or FALSE (Boolean) -- Custom function to query the database
$allow_download = check_if_downloadable('user_id', 'file_id', 'token_id');
record_download('user id', 'file id');

// After validation is complete, allow them to download
if ($allow_download === TRUE){
    header("Pragma: public");
...

If a user lost their download link (as it has happened many times), we show their download link on their member home page once they have logged in, and they can start downloading again (if you allow it).

I hope this helps. I'm sorry that I can't give out some code examples at this time.

Most of this is just querying the database.

Sometime in our website , need a download link. When click this link then any type of file,image, pdf will be download.You can do this using a simple php script.

want to download a picture name “shafiq_photo.jpg” so parameter is file name “shafiq_photo.jpg”. Then Create a php file name “download.php” which you use in above file.

<?php
 $file = $_GET["file"];

 if (file_exists($file)) {
 header('Content-Description: File Transfer');
 header('Content-Type: application/octet-stream');
 header("Content-Type: application/force-download");
 header('Content-Disposition: attachment; filename=' . urlencode(basename($file)));
// header('Content-Transfer-Encoding: binary');
 header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
 header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
 readfile($file);
 exit;
   }
 ?>

I would recommend to alter the logic:

But there is a security hole!

If two people start download that file with that link, then they can bypass payment for one. But what if someone download that file and send it to other. So, that isn't so much problem. isn't it?

But there is a option attach CSRF token if you think you should really safe.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM