[完]PHP文件下载 下载GET值中含有中文字符的文件,保存中文文件名,文件不能打开,遇到的编码问题

来源:互联网 发布:中英文即时口译软件 编辑:程序博客网 时间:2024/05/20 04:49

编码问题

  • 使用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服务器时,PHP文件编码格式设为“UTF-8无BOM编码”
    • 使用英文Windows 2008 服务器时,PHP文件格式设为“UTF-8编码”
  • 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: 中文.txtOS filename: ����.txtexist 

  如果去掉上述代码的header("Content-Type: text/html; charset=UTF-8");,采用Notepad,但是另存为编码“UTF-8”的文件,执行结果和上面一样。如果采用Notepad默认ANSI编码,执行结果则是:

GET filename: 涓枃.txtOS filename: 中文.txtexist 
  • 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下存在问题。

<?phpheader("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下存在问题。

<?phpheader("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系统设置中,将“当前系统区域设置”设置成相应的国家和语言。

0 0
原创粉丝点击