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
Download file using php script, one at time
提问by user1995997
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.
这是关于使用 php 脚本从服务器下载文件的问题。当用户点击下载链接时,它处理成download.php
文件,并使用header
它开始下载。
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.
下载文件后,文件中有一个功能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
.htaccess
we 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 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.
- 处理付款并捕获可下载文件的 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:
我建议改变逻辑:
- Deduct money first.
- Generate a random string. Save file and user info with it.
- In the client profile dump a download link with the random identifier. I mean http://www.example.com/download.php?file=254fd1f5df4df2sd5fsd5f4sdfsd0fsdf5sd4fsdf5dfsdf
- Onload complete remove the database entry.
- 先扣钱。
- 生成随机字符串。用它保存文件和用户信息。
- 在客户端配置文件中转储带有随机标识符的下载链接。我的意思是http://www.example.com/download.php?file=254fd1f5df4df2sd5fsd5f4sdfsd0fsdf5sd4fsdf5dfsdf
- Onload 完成删除数据库条目。
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 令牌。