1

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');
user1995997
  • 581
  • 2
  • 8
  • 19
  • 1
    This may get handy... http://stackoverflow.com/questions/14233850/how-to-prevent-file-hotlink-from-internet-download-manager-idm .. The idea is to block these download managers.. there are other ideas. But this is one of them... – Hiren Pandya Apr 11 '13 at 04:56
  • Are you charging per download on a video? your better off having a pay-per view and embed it on your webpage aren't you? If you are charging for the entire video, just let the customer 'buy' a video and then download it as many times as they want (or set a limit on it) – Benjamin Kaiser Apr 11 '13 at 04:57
  • 4
    Not too sure how you would have this setup for your users, but I recently completed something similar. When they go to download this, a unique URL will be displayed (download/) which they will use. If they attempted to process this again, the previous token will be used. Of course, this only works for when an active session is in place. – Dave Apr 11 '13 at 05:02
  • @BenjaminKaiser, There are not only videos, but softwares, mp3s, images and much more. After clicking on buy button, download starts. But after that I don't want user to download that file again. This site is not to be used on internet, I am using it on local lan server (Intranet). – user1995997 Apr 11 '13 at 05:02
  • @Cumbo, I got point on how to do this. Please describe this in brief as answer. – user1995997 Apr 11 '13 at 05:07
  • @user1995997 why not just limit it to say, 3 downloads then? could that work? – Benjamin Kaiser Apr 11 '13 at 05:25
  • @BenjaminKaiser, How to do that? I can't limit number of downloads. – user1995997 Apr 11 '13 at 05:28
  • Store in the database how many times they have downloaded the file they purchased and when it hits >2 give them an error telling them they cannot download it again. This solution involves you not taking the money off at the end of the download, but at a different step (e.g. when they click a buy button) – Benjamin Kaiser Apr 11 '13 at 06:16
  • @Cumbo sorry, I didn't read that comment properly before answering. But our answer may be so much identical. I would like if someone delete my answer. I am really sorry for the duplication. Any way I did it before for OTP system. that is how i get the answer. –  Apr 11 '13 at 07:44

3 Answers3

2

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, e.g: 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, e.g.: 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.

Dave
  • 862
  • 10
  • 20
1

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;
   }
 ?>
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Shafiqul Islam
  • 5,570
  • 2
  • 34
  • 43
0

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.