【问题标题】:php encoding - can't download if my file is saves using greek charactersphp 编码 - 如果我的文件使用希腊字符保存,则无法下载
【发布时间】:2012-04-30 23:11:52
【问题描述】:

我正在创建一些下载链接。我的问题是,如果“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>

还有我的 download.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;
        }
    }
?>

【问题讨论】:

  • 当您请求scripts/download.php?file=MY_FILE_NAME.doc 时得到的HTTP 响应是什么?
  • 你有没有尝试过其他的文件输出方式,比如readfile?
  • 如果下载,我看不到 http 响应。如果没有,我会看到我的错误消息。

标签: php encoding


【解决方案1】:

您的脚本中可能有几个问题:

1.文件系统编码问题

要实际访问文件系统上的文件,您必须正确编码文件名。 LC_CTYPE 语言环境参数告诉磁盘上文件名的预期编码。

在 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 = "应用程序/pdf"; # MIME 类型 $file_path = "绝对/或/相对/路径/文件"; header("内容类型:$file_mime"); header("内容长度:" .filesize($file_path)); $agent = $_SERVER["HTTP_USER_AGENT"]; if( is_int(strpos($agent, "MSIE")) ){ # 删除保留字符::\/*?"| $fn = preg_replace('/[:\\x5c\\/*?"|]/', '_', $file_name); # 非标准 URL 编码: header("内容配置:附件;文件名=" . rawurlencode($fn)); } else if( is_int(strpos($agent, "Gecko")) ){ # RFC 2231: header("内容配置:附件;文件名*=UTF-8''" . rawurlencode($file_name)); } else if( is_int(strpos($agent, "Opera")) ) { # 删除保留字符::\/*{? $fn = preg_replace('/[:\\x5c\\/{?]/', '_', $file_name); # RFC 2231: header("内容配置:附件;文件名*=UTF-8''" . rawurlencode($fn)); } 别的 { # RFC 2616 ASCII-only 编码: $fn = mb_convert_encoding($file_name, "US-ASCII", "UTF-8"); $fn = (string) str_replace("\\", "\\\\", $fn); $fn = (string) str_replace("\"", "\\\"", $fn); header("内容配置:附件;文件名=\"$fn\""); } 读取文件($file_path);

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    我认为问题出在 [您的脚本和文件系统之间] 的编码上。

    验证您在底层文件系统上使用的编码,因为这就是您访问文件的方式(即文件系统是否使用 iso-8859-1 [或类似的],并且您将变量作为 UTF-8 发送- 那么有一个问题。

    或者它可能就像您应该对从 get 获得的 var 执行 urldecode 一样简单(您可能还需要在此之后进一步对其进行编码以达到文件系统的编码)。

    $filename = urldecode($_GET['file']);
    

    【讨论】:

    • 我的 php.ini 有 default_charset = "utf-8"。 urldecode...没用!
    • 这可能不会影响用户单击链接时浏览器完成的url_encoding,因为这是由borwser完成的。文件系统是否也使用 utf-8 文件名存储带有希腊字符的文件?
    • "文件系统存储文件"???我只是将文件复制粘贴到我的下载文件夹中。
    • 首先要找出问题所在。 Echo $_GET, echo urldecode($_GET, echo utf8_encode(urldecode($_GET ... 然后看看你得到了你期望的输出的字符。如果你仍然无法读取文件,找出服务器上使用的 endocing并将文件名转换为该编码 - 大多数情况下,使用磁盘上没有 nls 字符的文件名更简单,但这并不总是有效(即,在保存到磁盘之前对文件名进行编码,但这并不总是一种选择)。
    • 在这种情况下,stackoverflow.com/questions/1089966/… 的帖子也可能对您有所帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 2012-04-30
    • 2013-03-02
    • 1970-01-01
    • 2012-06-25
    相关资源
    最近更新 更多