PHP 标头混乱

发布于 2024-12-16 23:37:01 字数 1878 浏览 1 评论 0原文

我一整天都在用头撞这个。是时候寻求一些帮助了。

所以,我有一个 PHP 脚本,它是一个下载页面。用户可以根据他们订购的内容下载文件。

它是这样的(显然不是真正的代码,有些位是 - 希望你能明白要点)

PAGE START
if(post[getorder]){

check order exists, get order filename etc from mysql;
update download attempts in db;

$ctype="application/force-download";
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); // required for certain browsers 
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
$handle = fopen($filename, "r");
while ( $contents = fread( $handle, 1024 ) )
{
print (  $contents );
flush();
}
fclose($handle);    
$successmessage = "Your download has begun";                  
}

if($successmessage){
 echo $successmessage;
}

get users order details from db;
display div
 display form with post to post order number to script; 
 end form
end div
END PAGE

希望这是有道理的。如果这会更有用的话,我可以放置所有代码,但这是一个很长的旧脚本,我认为这可能更方便。

因此,如果用户只是查看页面,脚本会抓取用户可能拥有的任何订单的订单信息。在订单被标记为完成且不再可用之前,用户只能尝试 X 次下载。

它为每个可用订单显示一个 div,每个 div 内都有一个小表单。如果他们单击表单,它会将订单号发送回同一脚本,此时我希望它只是提供文件,然后继续显示页面的其余部分。唉,不,显然强制下载的标头抓住了控制权,并且 fclose 之后没有任何反应。

所以我想搞砸了,并沿着 $sendfile = 1 的行在“if(post...)”中添加了一个变量,就在页面的底部...

if($sendfile == 1){做标题的东西}

...希望页面在发送文件之前能够正确加载并且每个人都高兴。再说一次,可惜没有。它首先提供文件,并且不重新加载页面。

再次,希望我的措辞有意义。

我读过,php 脚本将首先“处理”标头,因此将它们放在哪里并不重要。我不知道这是否属实,但根据我所看到的情况,确实如此。

我还尝试在 fclose 之后使用标头重定向到同一页面,并使用简单的 GET 使脚本显示成功消息。但是,如果我这样做,重新加载会起作用,但不会显示下载提示。即使我在重定向到 self 之前放置了 sleep(10) 。它只是等待然后重新加载,但没有文件下载。

页面重新加载非常重要,因为当页面的其余部分重新获取订单数据并显示它时,下载尝试次数应该增加 1。

有什么方法可以实现我想要做的事情吗?我正在切割的代码变得越来越hacky,因此任何帮助或建议将非常感激。

I've been banging my head against this one all day long. Time to ask for some help.

So, I have a PHP script, which is a downloads page. Users have files they can download according to what they have ordered.

It goes something like this (not real code obviously, well some bits are - hopefully you can get the gist)

PAGE START
if(post[getorder]){

check order exists, get order filename etc from mysql;
update download attempts in db;

$ctype="application/force-download";
header("Pragma: public"); // required
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false); // required for certain browsers 
header("Content-Type: $ctype");
header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
$handle = fopen($filename, "r");
while ( $contents = fread( $handle, 1024 ) )
{
print (  $contents );
flush();
}
fclose($handle);    
$successmessage = "Your download has begun";                  
}

if($successmessage){
 echo $successmessage;
}

get users order details from db;
display div
 display form with post to post order number to script; 
 end form
end div
END PAGE

Hopefully that makes sense. I can put all the code if that would be more useful, but it's a long old script and I thought this might be more convenient.

So, if a user is just viewing the page, the script grabs the user's order information on any orders they might have. Users only get X attempts to download before the order is flagged complete and no longer available.

It displays a div per available order, and inside each div is a small form. If they click on the form, it posts the order number back to the same script at which point I'd hoped it would simply serve the file then continue displaying the rest of the page. Alas no, apparently the headers on the force download grab control and nothing happens after the fclose.

So I thought bugger it, and added a variable into the "if(post...)" along the lines of $sendfile = 1, and right at the bottom of the page...

if($sendfile == 1){ do headers stuff}

...hoping that the page would load up correctly before sending the file and everyone happy. Again, alas no. It serves the file first, and doesn't reload the page.

Again, hopefully my verbiage makes some sense.

I've read that a php script will 'do' the headers first, so doesn't matter where you put them. I don't know if that is true, but based upon what I am seeing, it is.

I've also tried using headers after the fclose to redirect to the same page, and use a simple GET to make the script display the success message. However if I do this, the reload works, but the download prompt does not display. Even if I put a sleep(10) before the redirect to self. It just waits and then reloads, but no file download.

The page re-load is quite important, because when the rest of the page re-gets the order data and displays it, the download attempts should be increased by 1.

Is there any way to achieve what I am trying to do? The code I am cutting is getting increasingly more hacky so any help or suggestions would be very much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浮生未歇 2024-12-23 23:37:01

在下载登录页面上,尝试添加 而不是使用标头。这将使浏览器加载页面,然后 1 秒后重定向到文件下载。

此外,如果您要提供小文件以外的任何内容,我建议您查看 X-Sendfile

On the download landing page, try adding <meta http-equiv="refresh" content="1; url=/download/file/url"> instead of using headers. This will make the browser load the page, then after 1 second redirect to the file download.

Additionally, if you are serving anything other than small files, I'd recommend that you check out X-Sendfile.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文