我使用X-SendFile Apache模块从服务器下载大文件。下载效果良好。然而,当下载开始时,我需要向浏览器输出一些文本,例如:"感谢您下载该文件"
我的问题是,我不能在一个脚本中同时做到这两件事。我可以下载文件,然后没有文本输出到屏幕上。或者,我可以将文本输出到屏幕上,但下载脚本不会启动。
如何在一个PHP脚本中完成这两项任务-下载文件并将文本内容发送到浏览器/网页这个问题可能源于HTTP输出头,但我不知道如何解决。
这是我用来通过X-SendFile
下载文件的示例代码(单独正常工作):
header('Content-Description: File Transfer');
header("Content-Disposition: attachment; filename='"". basename($filePath) . "'"");
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
header('Content-Length: ' . filesize($filePath));
header("X-Sendfile: $filePath");
为了完成,这是我的测试echo""
字符串。如果它被放置在X-Sendfile
代码之上,它会得到输出,但下载不会开始。如果将其放在X-Sendfile
代码下方,则会下载该文件,但浏览器不会回显任何符号:
echo "SUCCESS!!!";
ob_flush();
约束:
我需要能够通过URL轻松下载文件。示例,www.mydomain.com/?fileID=asl523n53twteHLfga
。换句话说,PHP下载脚本在index.php
中。当用户输入www.mydomain.com
时,将显示域登录页。然而,当传递额外的$_GET
变量时,PHP脚本会识别出这一点,并且应该显示感谢您下载而不是登录页。
欢迎使用变通方法。重要的是在保持上述约束的同时获得所需的结果。非常感谢你。
如何添加一个单独的下载页面来下载文件(即download.php?fileID=XYZ
),并让索引页面显示这样的消息:
<?php
function homeScreen() {
// your home content
}
function downloadFileScreen ($id) {
?>
<h2>Thank you for your download!</h2>
Your download should start automatically, if it does not, click
<a href="download.php?fileID=<?php print $id; ?>">here</a>
<script type="text/javascript">
window.setTimeout('location.href="download.php?fileID=<?php print $id; ?>"',3000);
</script>
<?php
}
if (isset($_GET['fileID'])) {
$id= $_GET['fileID'];
downloadFileScreen ($id);
?>
} else {
// no ID passed, show home screen
homeScreen();
}
?>
我还没有听说任何浏览器支持在一个请求中混合下载和HTTP内容显示,但我会看看是否可以使用ob_start()
和ob_flush()
实现这一点。
有解决方法。您可以创建iframe,在其中下载文件。有关详细信息,请参阅代码。
感谢页面:(例如www.mydomain.com/?fileID=asl523n53twteHLfga)
<p>Thank you!</p>
<?php
$fileID = $_REQUEST['fileID'];
// csrf code individual for visitor, so visitor can's send direct link to friend
$csrf = md5(uniqid(rand(), true));
$_SESSION['csrf'] = $csrf;
// with iframe file will be downloaded 'in background'
echo '<iframe src="downloadFile.php?fileID=' . urlencode($fileID) . '&csrf=' . urlencode($csrf) . '" width="0" height="0"></iframe>';
?>
downloadFile.php(例如www.mydomain.com/downloadFile.php?fileID=asl523n53twteHLfga)
<?php
$fileID = $_REQUEST['fileID'];
if ($_REQUEST['csrf'] == $_SESSION['csrf'])
{
// download file
header('Content-Description: File Transfer');
header("Content-Disposition: attachment; filename='"". basename($filePath) . "'"");
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
header('Content-Length: ' . filesize($filePath));
header("X-Sendfile: $filePath");
die();
}
else
{
// csrf from request not equal csrf saved in session, so probably this is direct link to file received from other user
// redirect to 'thank you' page
header('Location: /?fileID=' . urlencode($fileID));
die();
}
?>