php 使用php脚本下载文件,一次一个

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15941006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 10:13:42  来源:igfitidea点击:

Download file using php script, one at time

phpdownload

提问by user1995997

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

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

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

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

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)

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

回答by Dave

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 .htaccesswe generated a download link, e.g.: http://domain.com/download/<token>the .htaccess contents:

    RewriteRule ^download/([a-z0-9-]) /download.php?token=
    
  • 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 0where 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.
  • 处理付款并捕获可下载文件的 IP 地址、文件和路径 - 将此信息保存到数据库中。
  • 成功扣除付款后,触发生成唯一令牌的函数,例如:sha1(microtime().$transactionid),并将其保存到数据库中(注意:请不要在生产中使用 microtime(),使用随机字符串生成器)。
  • 使用.htaccess我们生成了一个下载链接,例如:http://domain.com/download/<token>.htaccess 内容:

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

download.php

下载.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.

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

回答by Shafiqul Islam

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.

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

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.

想下载一个名为“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;
   }
 ?>

回答by user1995997

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.

但是,如果您认为您真的应该安全,则可以选择附加 CSRF 令牌。