PHP,X-SendFile:将文件与输出文本一起发送到浏览器(通过echo)


PHP, X-SendFile: Sending file together with outputting text to the browser (via echo)

我使用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();
}
?>