1

这是关于使用 php 脚本从服务器下载文件的问题。当用户点击下载链接时,它会处理为download.php文件,并使用header它开始下载。

下载文件后,文件中有一个功能download.php,它更新mysql数据库关于下载的文件并从用户帐户中扣款。一切正常。

现在,当用户在 pc 中安装了下载管理器时,就会出现问题。有时下载是在浏览器和下载管理器中开始的。因此,最后数据库中有两个下载条目,并且从用户帐户中扣除了两次钱。

问题:有没有办法一次只开始一次下载?或者任何其他方式来做这件事?

我提供给用户的下载链接。

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

我用于下载文件的脚本。(下载.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');
4

3 回答 3

2

将评论移至此处以供任何感兴趣的人使用。

我必须想出的功能是处理付款后的唯一下载链接。这些是已采取的步骤。

  • 处理付款并获取可下载文件的 IP 地址、文件和路径 - 将此信息保存到数据库。
  • 扣款成功后,触发生成唯一令牌的函数,例如:sha1(microtime().$transactionid),并将其保存到数据库中(注意:请不要在生产中使用 microtime() ,使用随机字符串生成器)。
  • 使用.htaccess我们生成的下载链接,例如:http://domain.com/download/<token>.htaccess 内容:

    RewriteRule ^download/([a-z0-9-]) /download.php?token=$1
    
  • 可选:如果他们的 IP 与我们在数据库中的 IP 匹配,请继续并允许用户下载文件。如果没有,我们会要求用户登录,以便我们可以更新他们的 IP 地址并开始下载。
  • 获得令牌后,您几乎可以从这里进行任何形式的验证,例如通过在数据库download_downloaded INT(1) DEFAULT 0中添加一列来防止多次下载,如果它设置为 1,则它已被下载。我建议在下载后将用户锁定前一天给用户,以防他们的文件在此过程中损坏。
  • 任何其他附加项目,例如下载计数器等。
  • 最后使用上面的代码开始下载。不过,我会让它的结构有所不同。

下载.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");
...

如果用户丢失了他们的下载链接(这种情况已经发生过很多次),一旦他们登录,我们就会在他们的会员主页上显示他们的下载链接,他们可以再次开始下载(如果您允许的话)。

我希望这有帮助。很抱歉,我现在不能给出一些代码示例。

其中大部分只是查询数据库。

于 2013-04-11T14:20:01.703 回答
1

有时在我们的网站上,需要一个下载链接。单击此链接时,将下载任何类型的文件、图像、pdf。您可以使用简单的 php 脚本执行此操作。

要下载图片名称“shafiq_photo.jpg”,所以参数为文件名“shafiq_photo.jpg”。然后创建一个您在上述文件中使用的 php 文件名“download.php”。

<?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;
   }
 ?>
于 2013-07-11T08:22:36.980 回答
0

我建议改变逻辑:

但是有一个安全漏洞!

如果两个人开始使用该链接下载该文件,那么他们可以绕过支付一个。但是,如果有人下载该文件并将其发送给其他人怎么办。所以,这不是什么大问题。不是吗?

但是如果你认为你应该非常安全,可以选择附加 CSRF 令牌。

于 2013-04-11T07:38:01.327 回答