使用 PHP 强制下载然后重定向
我知道这个问题以前已经被问过很多次了,但我找不到适合我需要的答案。
我需要找到一种方法来强制下载文件,然后在下载开始后重定向到“感谢下载”页面。
到目前为止,我已经:
<?php
ob_start();
$token = $_POST['validationCode'];
if(isset($token)){
$connect = mysql_connect('localhost', 'root', 'root');
$db = mysql_select_db('mydb');
if (!$connect || !$db){
die('Connect Error (' . mysql_connect_errno() . ') '
. mysql_connect_error());
}
$sql = mysql_query("SELECT * FROM emailaddresses WHERE token='$token'");
$result = mysql_fetch_array($sql);
if($result){
header('Location: complete.php');
header('Content-type: application/mp3');
header('Content-Disposition: attachment; filename=track.mp3');
$f = file_get_contents('downloads/track.mp3');
print $f;
$sql = "UPDATE emailaddresses SET download=1 WHERE token='$token'";
$result = mysql_query($sql);
}
else{
echo "There was a problem downloading the file" . mysql_error();
}
}
ob_end_flush();
?>
隐藏下载文件的位置很重要,否则我就会创建一个指向该文件的 HTML 链接。
显然我不能将重定向标头放在其他标头下方,因为它不起作用。除了在弹出窗口中打开它并将主窗口定向到“谢谢”页面之外,我真的不知道从这里该去哪里 - 但这是最后的手段。
有人可以提出任何建议吗?
干杯,
丰富
I know this question has been asked many times before but I can't find an answer to suit my needs.
I need to find a way to force the download of a file and then, after the download has started, redirect to a "thanks for downloading" page.
So far I have:
<?php
ob_start();
$token = $_POST['validationCode'];
if(isset($token)){
$connect = mysql_connect('localhost', 'root', 'root');
$db = mysql_select_db('mydb');
if (!$connect || !$db){
die('Connect Error (' . mysql_connect_errno() . ') '
. mysql_connect_error());
}
$sql = mysql_query("SELECT * FROM emailaddresses WHERE token='$token'");
$result = mysql_fetch_array($sql);
if($result){
header('Location: complete.php');
header('Content-type: application/mp3');
header('Content-Disposition: attachment; filename=track.mp3');
$f = file_get_contents('downloads/track.mp3');
print $f;
$sql = "UPDATE emailaddresses SET download=1 WHERE token='$token'";
$result = mysql_query($sql);
}
else{
echo "There was a problem downloading the file" . mysql_error();
}
}
ob_end_flush();
?>
It's important to hide the download file's location otherwise I would have just created an HTML link to the file.
I obviously can't put a redirect header below the other headers as it just won't work. I can't really see where to go from here apart from opening this in a pop-up and directing the main window to the "thank you" page - but that is a LAST resort.
Can anyone give any suggestions?
Cheers,
Rich
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
确实没有太多选择。如果您的主要目标是隐藏 URL,那么无论如何这都是失败的。为了获得良好的可用性,您通常会在页面上添加纯链接(“下载无法开始?单击此处...”),因为用户可能会意外取消在错误的时间进行重定向,从而不可挽回地终止下载。
您不能在同一请求/响应中输出文件本身以外的任何内容。您可以按照@netcoder的建议尝试多部分HTTP响应,但我不太确定它的支持程度。首先假设有一个“浪费”的请求/响应,其中仅下载了文件,没有发生任何其他事情。处理此限制的方式通常如下:
刷新或 HTTP
Refresh
标头,导致延迟重定向到文件的 URL。请参阅 http://download.com 了解此操作的示例。
您可以将文件的下载位置设置为仅在允许用户下载文件时才返回文件的脚本。您可以在“谢谢”页面和文件下载页面之间传递一些临时令牌,以验证是否允许下载。
There really isn't much choice. If your primary goal is to hide the URL, that's a lost cause anyway. For good usability, you usually include the plain link on the page anyway ("Download doesn't start? Click here..."), since the user may accidentally cancel the redirect at just the wrong time to irrevocably kill the download.
You cannot output anything other than the file itself in the same request/response. You could try multi-part HTTP responses as suggested by @netcoder, but I'm not really sure how well that's supported. Just start with the assumption that there's one "wasted" request/response in which only the file is downloaded and nothing else happens. The way things usually work with this restriction is like this:
<meta>
refresh or HTTPRefresh
header that causes a delayed redirect to the URL of the file.Look at http://download.com for an example of this in action.
You can make the download location for the file be a script that only returns the file if the user is allowed to download the file. You can pass some temporary token between the "Thank you" page and the file download page to verify that the download is allowed.
我所知道的 PHP 中唯一的方法(下载,然后重定向)是使用多部分 HTTP 响应。类似这样:
在您的情况下,您可以只输出“感谢下载”页面内容,而不是 JavaScript 重定向。
我不确定它是否适用于所有/主要浏览器。
The only way in PHP I know of (to have a download, then to redirect) is to use a multi-part HTTP response. Something like that:
In your case, you could just output the "Thanks for downloading" page content instead of the JavaScript redirect.
I'm unsure whether it works on all/major browsers or not.
好的,首先,浏览器需要知道文件位置才能下载它。任何打开 Firebug 等标准浏览器开发工具的人都可以以纯文本形式查看文件的 URL。
现在,我想您想保护您的文件免遭未经授权的下载。如果这就是你想要的,有一种方法可以使用会话。
在您的第一页上,您将输入代码来检查下载是否已授权。然后,您将把当前的内容与标识该文件的内容放入会话中。文件唯一的任何内容都可以,例如数据库 ID。
然后,你重定向到一个带有像这样的 html 元的页面,
在这个页面中你会说“谢谢你,小伙子下载了我很棒的文件”。请注意,如果您愿意,您还可以将“content”属性的内容放入头文件中,如下所示。
请注意,5 是直到出现下载文件对话框为止的秒数。
然后在 download.php 上您将执行以下操作:
1- 使用 $_GET['file'] 检查请求的文件。
2-然后检查 download_key 是否存在于会话中。如果不是,则退出脚本,如下所示
3-然后检查时间戳是否早于某个任意时间限制。这里用 30 秒
4- 最后,如果全部检查完毕,您将像这样发送文件
在 readfile 之后,您将在数据库中放置将下载设置为 1 的代码。
就是这样,受保护的文件下载,任何直接使用该 URL 的人都会看到一个大的“未经授权”文本。
我还想补充一点,如果你有一个大文件(超过几千字节),你最好禁用输出缓冲,因为这意味着 php 将在整个内存中保留文件的副本下载的持续时间。使用 readfile 函数,php 在磁盘上读取数据时将其发送到浏览器,因此将使用更少的内存(并且将更快地开始发送数据)。
编辑:使它起作用的是以下
我实际上颠倒了顺序:访问者首先被重定向到包含刷新标题/标签的感谢页面。刷新标头的神奇之处在于它会在内容加载后重定向。一旦进入感谢页面,浏览器就会看到该标头,然后在显示页面时等待指定的时间,然后重定向到下载。重定向后,浏览器会看到它是一个要下载的文件,并且不会更改页面,而是显示下载文件对话框。一旦用户单击“确定”,下载就会开始,但他将停留在同一页面上。
简而言之,文件下载后您不需要重定向,因为您已经位于感谢页面!我认为文件下载后甚至不可能重定向。只要看看当您单击指向网络服务器上的直接文件的链接时会发生什么。浏览器会提示下载,但不会中断您的导航。下载开始后,您可以愉快地点击链接离开页面。下载完成后,您可能会访问一个完全不同的网站。这就是为什么您之前只能显示感谢页面。但是,如果您为刷新标题/标签设置零,则页面加载后就会出现下载提示,因此几乎就像两者是同时发生的(在访问者看来)
Ok, first thing first, the browser need to know the file location to download it. Anyone opening a standard browser dev tool like Firebug will be able to see in plain text the URL of your file.
Now, I suppose you want to protect your file from unauthorised download. If that is what you want, there is a way for that using session.
On your first page, you will put your code to check if the download is authorized. You will then put in session the current with something that identify the file. Anything that is unique for the file will do, like the database id.
Then, you redirect to a page with a html meta like this
This is the page where you will say "Thank you fine lad for downloading my awesome file". Note that you can also put the content of the "content" attribute in a header file if you like, like this
Note that the 5 is the number of second until the download file dialog box appear.
Then on download.php you will do the following :
1- Check which file was requested using the $_GET['file'].
2- Then you check if the download_key exists in session. If not, you exit the script like that
3- Then you check if the timestamps is older than some arbitrary time limit. Here with 30 sec
4- Finally, if all check out, you send the file like that
After the readfile, you will put the code to set the download to 1 in the database.
And that's it, protected file download, and anybody using the URL directly will be greeted by a big "unauthorized" text.
I'd also like to add that if you have a big file (more than say a few kilobyte), you may be better off disabling output buffering, since that will mean that php will keep a copy of the file in memory for the whole duration of the download. With the readfile function, php will send it to the browser as it read it on the disk and thus will use less memory (and will start to send data sooner).
EDIT : What make it work is the following
I actually inverted the sequence : the visitor is first redirected to the thank you page which contain a Refresh header/tag. The magic of the Refresh header is that it redirect AFTER the content is loaded. Once on the thank you page, the browser seeing that header then wait for the specified time while showing the page, then redirect to the download. Once redirected, the browser see that its a file to be downloaded and instead of changing the page, just show the download file dialog. Once the user click OK, the download will start but he will stay on the same page.
In a nutshell, you don't need to redirect after the file download, since you are already on the thank you page! I don't think it's even possible to redirect after a file download. Just look at what happen when you click on a link that point to a direct file on the webserver. The browser prompt for download, but does not cut your navigation. Once the download is started, you can happily click away from the page with the link. By the time the download is over, you may be on a completely different Website. That is why you can only show the thank you page before. But if you put a zero for the refresh header/tag, the download prompt will appear as soon as the page is loaded, so it's almost as if the two were simultaneous (in the eye of the visitor)