[英]PHP readfile() causing corrupt file downloads
I am using php script to provide download from my website after a requisite javascript timer this php script is included which causes the download.我正在使用 php 脚本在必要的 javascript 计时器之后从我的网站提供下载,此 php 脚本包含在导致下载的内容中。 But the downloaded file is corrupt no matter whatever I try.但是无论我尝试什么,下载的文件都已损坏。 Can anyone help me point out where am I going wrong.谁能帮我指出我哪里出错了。
This is my code这是我的代码
<?php
include "db.php";
$id = htmlspecialchars($_GET['id']);
$error = false;
$conn = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD);
if(!($conn)) echo "Failed To Connect To The Database!";
else{
if(mysql_select_db(DB_NAME,$conn)){
$qry = "SELECT Link FROM downloads WHERE ID=$id";
try{
$result = mysql_query($qry);
if(mysql_num_rows($result)==1){
while($rows = mysql_fetch_array($result)){
$f=$rows['Link'];
}
//pathinfo returns an array of information
$path = pathinfo($f);
//basename say the filename+extension
$n = $path['basename'];
//NOW comes the action, this statement would say that WHATEVER output given by the script is given in form of an octet-stream, or else to make it easy an application or downloadable
header('Content-type: application/octet-stream');
header('Content-Length: ' . filesize($f));
//This would be the one to rename the file
header('Content-Disposition: attachment; filename='.$n.'');
//Finally it reads the file and prepare the output
readfile($f);
exit();
}else $error = true;
}catch(Exception $e){
$error = true;
}
if($error)
{
header("Status: 404 Not Found");
}
}
}
?>
This helped me in case of more output buffers was opened.这有助于我在打开更多输出缓冲区的情况下。
//NOW comes the action, this statement would say that WHATEVER output given by the script is given in form of an octet-stream, or else to make it easy an application or downloadable
header('Content-type: application/octet-stream');
header('Content-Length: ' . filesize($f));
//This would be the one to rename the file
header('Content-Disposition: attachment; filename='.$n.'');
//clean all levels of output buffering
while (ob_get_level()) {
ob_end_clean();
}
readfile($f);
exit();
First of all, as some people pointed out on the comments, remove all spaces before the opening PHP tag ( <?php
) on the first line and that should do the trick (unless this file is included or required by some other file).首先,正如一些人在评论中指出的那样,删除第一行开始 PHP 标记( <?php
)之前的所有空格,这应该可以解决问题(除非其他文件包含或需要该文件)。
When you print anything on the screen, even a single space, your server will send the headers along with the content to be printed (in the case, your blank spaces).当您在屏幕上打印任何内容时,即使是单个空格,您的服务器都会发送标题以及要打印的内容(在这种情况下,您的空格)。 To prevent this from happening, you can:为了防止这种情况发生,您可以:
a) not print anything before you're done writing the headers; a) 在写完标题之前不要打印任何东西;
b) run an ob_start() as the first thing in your script, write stuff, edit your headers and then ob_flush() and ob_clean() whenever you want your content to be sent to the user's browser. b) 运行 ob_start() 作为脚本中的第一件事,编写内容,编辑标题,然后在您希望将内容发送到用户浏览器时运行 ob_flush() 和 ob_clean()。
In b), even if you successfully write your headers without getting an error, the spaces will corrupt your binary file .在 b) 中,即使您成功写入标头而没有出错,空格也会损坏您的二进制文件。 You should only be writing your binary content, not a few spaces with the binary content.您应该只编写二进制内容,而不是包含二进制内容的几个空格。
The ob_ prefix stands for Output Buffer. ob_前缀代表输出缓冲区。 When calling ob_start()
, you tell your application that everything you output ( echo
, printf
, etc) should be held in memory until you explicitly tell it to 'go' ( ob_flush()
) to the client.调用ob_start()
,您告诉应用程序您输出的所有内容( echo
、 printf
等)都应保存在内存中,直到您明确告诉它“转到”( ob_flush()
)到客户端ob_flush()
。 That way, you hold the output along with the headers, and when you are done writing them, they will be sent just fine along with the content.这样,您将输出与标题一起保存,当您完成编写它们时,它们将与内容一起发送。
ob_start();//add this to the beginning of your code
if (file_exists($filepath) && is_readable($filepath) ) {
header('Content-Description: File Transfer');
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=$files");
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header("content-length=".filesize($filepath));
header("Content-Transfer-Encoding: binary");
/*add while (ob_get_level()) {
ob_end_clean();
} before readfile()*/
while (ob_get_level()) {
ob_end_clean();
}
flush();
readfile($filepath);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.