>我正在创建一些下载链接。我的问题是,如果使用英文字符保存"MY_FILE_NAME.doc"文件,则正在下载。如果我使用希腊字符保存它,那么我无法下载...我正在使用 utf-8 编码。
(我不知道这是否重要,但我在我的页面上显示希腊字符没有任何问题(
这是我的链接:
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>CFS Portal</title>
</head>
<body>
<div>
<span class="txt">
<a href="scripts/download.php?file=MY_FILE_NAME.doc" class="dload">Ιατρικό</a>
</span></div>
</body>
和我的下载.php文件:
<?php
// block any attempt to the filesystem
if (isset($_GET['file']) && basename($_GET['file']) == $_GET['file']) {
$filename = $_GET['file'];
} else {
$filename = NULL;
}
$err = '<p class="err_msg">
STOP / ΣΤΑΜΑΤΗΣΤΕ
</p>';
if (!$filename) {
// if variable $filename is NULL or false display the message
echo $err;
} else {
// define the path to your download folder plus assign the file name
$path = 'downloads/'.$filename;
// check that file exists and is readable
if (file_exists($path) && is_readable($path)) {
// get the file size and send the http headers
$size = filesize($path);
header('Content-Type: application/octet-stream;');
header('Content-Length: '.$size);
header('Content-Disposition: attachment; filename='.$filename);
header('Content-Transfer-Encoding: binary');
// open the file in binary read-only mode
// display the error messages if the file can´t be opened
$file = @ fopen($path, 'rb');
if ($file) {
// stream the file and exit the script when complete
fpassthru($file);
exit;
} else {
echo $err;
}
} else {
echo $err;
}
}
?>
脚本中可能存在几个问题:
1. 文件系统编码问题
要实际访问文件系统上的文件,您必须正确编码文件名。LC_CTYPE locale 参数告诉磁盘上文件名的预期编码。
在 Unix/Linux 或类似操作系统下,该参数的计算结果可能类似于"en_US。UTF-8",这意味着文件名的编码为 UTF-8,因此脚本中不需要转换。
在 Windows 服务器下,不允许使用 UTF-8,通常LC_CTYPE计算结果为"language_country.codepage",其中"codepage"是当前活动代码页的编号,例如 1252(西方国家(或 1253(希腊语(。这里 http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/是Windows下可用代码页的列表。然后,在Windows下,您需要将UTF-8文件名转换为其他名称才能从磁盘读取它。更多细节可以在我对PHP错误号47096的回复中找到,网址为:https://bugs.php.net/bug.php?id=47096
2. HTTP文件名编码问题
根据我的经验,不同的浏览器支持不同的方式对非 ASCII 文件名进行编码,并且在存在特殊或无效字符时的行为也不同(例如,在 Windows 下,文件名中不允许使用问号"?",浏览器要么简单地删除该字符,要么将整个文件名完全替换为另一个随机生成的文件名(。无论如何,以下代码块适用于大多数浏览器:
$file_name = "Caffé Brillì.pdf"; # 文件名,UTF-8 编码 $file_mime = "application/pdf"; # 哑剧类型 $file_path = "绝对/或/相对/路径/文件"; header("Content-Type: $file_mime"(; 标头("内容长度: " .文件大小($file_路径((; $agent = $_SERVER["HTTP_USER_AGENT"]; if( is_int(strpos($agent, "MSIE"(( ({ # 删除保留字符::''/*?"| $fn = preg_replace('/[:''''x5c''''/*?"|]/', '_' , $file_name(; # 非标准网址编码: 标头("内容处置:附件;文件名=" .rawurlencode($fn((; } else if( is_int(strpos($agent, "Gecko"(( ({ # RFC 2231: 标头("内容处置:附件;文件名*=UTF-8''" .rawurlencode($file_name((; } else if( is_int(strpos($agent, "Opera"(( ( { # 删除保留字符: :''/*{? $fn = preg_replace('/[:''''x5c''''/{?]/', '_' , $file_name(; # RFC 2231: 标头("内容处置:附件;文件名*=UTF-8''" .rawurlencode($fn((; } else { # RFC 2616 仅 ASCII 编码: $fn = mb_convert_encoding($file_name, "US-ASCII", "UTF-8"(; $fn = (字符串( str_replace("''''", "''''''''", $fn(; $fn = (字符串( str_replace("''", "''''''", $fn(; 标头("内容处置:附件;文件名=''"$fn''"(; } 读取文件($file_路径(;
希望这可能会有所帮助。
我认为问题出在[脚本和文件系统之间]的编码上。
验证您在底层文件系统上使用的编码,因为这是您访问文件的方式(即文件系统使用 iso-8859-1 [或类似] 并且您将变量作为 UTF-8 发送 - 然后存在问题。
或者它可能很简单,你应该对你从get获得的var做一个urldecode(你可能还需要在此之后进一步编码它以达到文件系统的编码(。
$filename = urldecode($_GET['file']);