[完]PHP檔案下載 下載GET值中含有中文字元的檔案,儲存中文檔名,檔案不能開啟,遇到的編碼問題
阿新 • • 發佈:2019-01-31
編碼問題:
使用Windows Server 2008英文版作為伺服器,檔案系統中檔名儲存的編碼與Windows“當前系統區域設定”相關。(例如:中文預設為GB2312,俄文為西里爾文Windows[windows-1251])
文字編輯器採用的編碼。
- Windows Notepad預設的文字編碼是ANSI。
- Notepad++,可以通過“格式 | 轉為UTF-8無BOM編碼格式”,將編碼轉化為UTF-8無BOM格式。採用伺服器的語言版本不一樣時,有所差別,英文Windows 2008伺服器時,PHP檔案格式設為“UTF-8編碼”,這樣下載的檔案才能正確開啟。
開啟下載的檔案出現問題。
- 使用中文Windows 2008
- 使用英文Windows 2008 伺服器時,PHP檔案格式設為“UTF-8編碼”
- 使用中文Windows 2008
Web伺服器採用Apache。預設編碼為UTF-8,GET值的編碼也是UTF-8。
# 設定PHP頁採用的編碼,如果使用Windows自帶的Notepad編碼,且不在首行設定編碼,那麼預設採用的是ANSI編碼
header("Content-Type: text/html; charset=UTF-8");
$getFile = $_GET['f'];
echo 'GET filename: ' . $getFile . '<br/>';
# 將get中獲取的filename轉換成os認識的filename,這樣file_exists()才認,才能下載相應檔案。
$osFile = iconv('utf-8','GB2312', $getFile);
echo 'OS filename: ' . $osFile . '<br/>';
if( file_exists($osFile) ) {
echo 'exist';
} else {
echo 'not exist';
}
http://192.168.1.102/test.php?f=中文.txt
的執行結果
GET filename: 中文.txt
OS filename: ����.txt
exist
如果去掉上述程式碼的header("Content-Type: text/html; charset=UTF-8");
GET filename: 涓枃.txt
OS filename: 中文.txt
exist
- basename($pFileName):對含有中文字元的檔名無效,解決方法:
end(explode('/',$pFileName));
- file_exists($fileName):對解析中文檔名有問題。主要是編碼問題,只有將檔名轉換為Windows伺服器“當前系統區域設定”中語言採用的預設語言編碼才行。
- IE瀏覽器中,即使頁面預設選擇是UTF-8,連結中中文字串依然使用GB2312編碼,看下面程式碼在不同瀏覽器中執行var_dump()函式的結果
header("Content-Type: text/html; charset=UTF-8");
$getFile = $_GET['f'];
echo 'var_dump getFile: ';
var_dump($getFile);
echo '<br/>';
PHP頁面程式碼如上,使用http://192.168.1.102/test1.php?f=中文
,訪問頁面。在不同瀏覽器中結果。
360,Chrome,Firefox | IE |
---|---|
var_dump getFile: string(6) "中文" |
var_dump getFile: string(4) "����" |
使用一種為每個檔案建立一個數字目錄,去目錄下搜尋檔案並下載,繞過GET傳中文檔名。規避了各種編碼問題。但是如果不注意Windows中“當前系統區域設定”的話,由中文伺服器換到英文伺服器上,會出現問題,需要將“當前系統區域設定”設定到“中文(簡體,中國)”。
程式程式碼
下面程式碼可在360,Chrome和Firefox正常使用,但在IE下存在問題。
<?php
header("Content-Type: text/html; charset=UTF-8");
$getFile = $_GET['f'];
# 將瀏覽器傳入的UTF-8編碼的檔名,轉換成Windows伺服器認的GB2312編碼,然後才能下載相關檔案
$osFile = iconv('UTF-8','GB2312', $getFile);
downfile('./d/'.$osFile);
function downfile($osFile) {
if(file_exists($osFile)) {
# basename() 消除檔案路徑,只保留檔名,對於中文出現問題,應該就是編碼問題,
# 處理好編碼問題,應該可以使用basename()函式
# $saveName = basename($osFile);
$saveName = end(explode('/', $osFile));
# 將Windows伺服器認的GB2312編碼,轉換成瀏覽器認的UTF-8編碼
$saveName = iconv('GB2312', 'UTF-8', $saveName);
header("Content-Type: application/octet-stream");
header("Accept-Ranges: bytes");
# 計算檔案大小,使用Windows伺服器認的GB2312編碼
header("Accept-Length: ".filesize($osFile));
# 在瀏覽器端儲存檔案,使用瀏覽器認的UTF-8編碼
header("Content-Disposition: attachment; filename=\"{$saveName}\"");
# 讀取檔案,使用Windows伺服器認的GB2312編碼
readfile($osFile);
} else {
echo "The file is not exist!";
}
}
?>
下面程式碼可在IE,Chrome和Firefox正常使用,但在360下存在問題。
<?php
header("Content-Type: text/html; charset=UTF-8");
$getFile = $_GET['f'];
# 將瀏覽器傳入的UTF-8編碼的檔名,轉換成Windows伺服器認的GB2312編碼,然後才能下載相關檔案
$osFile = iconv('UTF-8','GB2312', $getFile);
$osPathFile = './d/'.$osFile;
$browser = $_SERVER['HTTP_USER_AGENT'];
# 如果是IE的話
if( strpos($browser, "Trident") > -1 || strpos($browser, "MSIE") > -1) {
# 獲取儲存檔名
$saveFile = $getFile;
downFileIE( $osPathFile, $saveFile);
# mb_convert_encoding與iconv功能類似,但是它是將第一個引數的原來編碼放在最後一個引數位置,需要轉變的編碼是第二個引數
} else {
downFile($osPathFile);
}
function downFile($osPathFile) {
if(file_exists($osPathFile)) {
# basename() 消除檔案路徑,只保留檔名,對於中文出現問題,應該就是編碼問題,
# 處理好編碼問題,應該可以使用basename()函式
# $saveName = basename($osFile);
$saveName = end(explode('/', $osPathFile));
# 將Windows伺服器認的GB2312編碼,轉換成瀏覽器認的UTF-8編碼
$saveName = iconv('GB2312', 'UTF-8', $saveName);
header("Content-Type: application/octet-stream");
header("Accept-Ranges: bytes");
# 計算檔案大小,使用Windows伺服器認的GB2312編碼
header("Accept-Length: ".filesize($osPathFile));
# 在瀏覽器端儲存檔案,使用瀏覽器認的UTF-8編碼
header("Content-Disposition: attachment; filename=\"{$saveName}\"");
# 讀取檔案,使用Windows伺服器認的GB2312編碼
readfile( $osPathFile);
} else {
echo "The file is not exist!";
}
}
function downFileIE($osPathFile, $saveFile) {
if(file_exists($osPathFile)) {
header("Content-Type: application/octet-stream");
header("Accept-Ranges: bytes");
# 計算檔案大小,使用Windows伺服器認的GB2312編碼
header("Accept-Length: ".filesize($osFile));
# 在瀏覽器端儲存檔案,使用瀏覽器認的UTF-8編碼
header("Content-Disposition: attachment; filename=\"{$saveFile}\"");
# 讀取檔案,使用Windows伺服器認的GB2312編碼
readfile('./d/'.$saveFile);
} else {
echo "The file is not exist!";
}
}
?>
如果伺服器儲存的是其他國家語言的文字,可以統一將程式中GB2312編碼,轉換相應國家的語言編碼,注意在Windows系統設定中,將“當前系統區域設定”設定成相應的國家和語言。