[英]PHP readfile() causing corrupt file downloads
我正在使用 php 腳本在必要的 javascript 計時器之后從我的網站提供下載,此 php 腳本包含在導致下載的內容中。 但是無論我嘗試什么,下載的文件都已損壞。 誰能幫我指出我哪里出錯了。
這是我的代碼
<?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");
}
}
}
?>
這有助於我在打開更多輸出緩沖區的情況下。
//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();
首先,正如一些人在評論中指出的那樣,刪除第一行開始 PHP 標記( <?php
)之前的所有空格,這應該可以解決問題(除非其他文件包含或需要該文件)。
當您在屏幕上打印任何內容時,即使是單個空格,您的服務器都會發送標題以及要打印的內容(在這種情況下,您的空格)。 為了防止這種情況發生,您可以:
a) 在寫完標題之前不要打印任何東西;
b) 運行 ob_start() 作為腳本中的第一件事,編寫內容,編輯標題,然后在您希望將內容發送到用戶瀏覽器時運行 ob_flush() 和 ob_clean()。
在 b) 中,即使您成功寫入標頭而沒有出錯,空格也會損壞您的二進制文件。 您應該只編寫二進制內容,而不是包含二進制內容的幾個空格。
ob_前綴代表輸出緩沖區。 調用ob_start()
,您告訴應用程序您輸出的所有內容( echo
、 printf
等)都應保存在內存中,直到您明確告訴它“轉到”( ob_flush()
)到客戶端ob_flush()
。 這樣,您將輸出與標題一起保存,當您完成編寫它們時,它們將與內容一起發送。
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.