php - 是否可以从 PHP 文件发送标头,这完全没有任何作用
问题描述
在我提供音乐样本下载的页面上,我有几个<a>
标签,其 href 指向 PHP 文件。作为 GET 变量包含的各种数据允许下载正确的文件。通常,PHP 会以典型的下载标头响应,然后是 readfile()。(代码如下,仅供参考)。这会导致干净的下载(或某些浏览器上的下载/播放对话框)。通过“干净”,我的意思是下载完成,访问者页面没有干扰。
但是,万一请求的文件不可用,我不知道该怎么办。我知道它不应该发生,但如果发生了,我希望下载链接什么也不做。不幸的是,因为它是一个<a>
引用 PHP 文件的标签,所以什么都不做会导致浏览器清除页面,并在地址栏中显示 PHP 文件的 URL。游客体验不好!因此,如果有错误的请求,我想避免干扰页面并且什么都不做。我将使用 javascript 来提醒访问者出了什么问题,但我不能让错误的文件请求清除页面!
我以为我已经通过发出 header('Location: #'); 找到了解决方案。当脚本检测到不可能的文件下载时。但几秒钟后,浏览器清除了该页面并显示一条消息,指出该页面“重定向您太多次”。(事实上,我的脚本日志中有 100 多个条目,尽管我只单击了一次标签。)
到目前为止,我唯一可行的解决方案(如果请求“不可用”文件,则不会干扰访问者页面)是将我的下载标题指向“虚拟”文件。一个实际的“silence.mp3”或“nosong.mp3”文件。但是有没有办法调用一个对调用页面没有任何作用的 header() ?简单地调用 exit 或 exit() 将不起作用(访问者页面被重定向为空白。)
没关系,但这是我通常为响应 d/l 请求而调用的代码......
function downloadFile($path) {
$path_parts = pathinfo($path);
$ext = strtolower($path_parts["extension"]); // don't need this.
$fsize =fileExists($path);
if ($fsize == 0)
{
header('Location: #'); // this doesn't work!!! (too many redirectcts)
exit;
}
//$dlname = $path_parts['filename'] . "." . strtolower($path_parts["extension"]);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: filename=\"" . $path_parts["basename"]."\"");
header("Content-Type: application/x-file-to-save");
header("Content-Transfer-Encoding: binary");
if($fsize) header("Content-length: $fsize");
$bytesRead = readfile($path);
return $bytesRead;
}
解决方案
如果您使用带有标准锚标记的 HTTP/1.x,没有 JavaScript 或其他客户端拦截。当单击返回 204 状态标头的HTTP/1.0 204 No Content
链接时,状态标头将导致用户代理看起来像没有发生任何事情。
HTTP/1.0 204 No Content
服务器已完成请求,但没有新信息要发回。如果客户端是用户代理,它不应该改变 导致请求生成的文档视图。这个响应主要是为了允许脚本的输入或其他动作发生,而不会导致用户代理的 活动文档视图发生变化。响应可能包含实体标题形式的新元信息,它应该应用于当前在用户代理的活动视图中的文档。
来源:https ://www.w3.org/Protocols/HTTP/1.0/spec.html#Code204
这也与HTTP/1.1
协议兼容。
我建议使用输出缓冲来确保您的应用程序不会错误地发送其他内容。此外,应该不需要发送Content-Length
标头。
function downloadFile($path) {
if (!is_file($path) || !($fsize = filesize($path))) {
header('HTTP/1.0 204 No Content');
exit;
}
$path_parts = pathinfo($path);
header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Disposition: filename="' . $path_parts['basename'] . '"');
header('Content-Type: application/x-file-to-save');
header('Content-Transfer-Encoding: binary');
header('Content-length: ' . $fsize); //fsize already validated above.
return readfile($path);
}
推荐阅读
- firebase - firebase 项目的受邀所有者无法部署云功能
- python - Bot 连接到聊天但不播放音频 - Discord.py 重写
- c# - 仅当布尔为真时才激活功能?
- c# - 为什么 rnd.Next 没有给我最大值
- python - 权限被拒绝 mv /usr/bin
- java - Java:如何创建一个接受第一个元素列表的列表 cons
- python - 如何在Python中的一组列表中找到被支配的列表(对于所有可能的索引,如果list1 [index] <= list2 [index],list1被支配)
- javascript - 如何根据 localStorage 状态选中/取消选中复选框
- javascript - 如何在不影响内部元素的情况下背景图片缩放动画
- flutter - 滚动列表视图时容器 BlendMode 消失 - Flutter