首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Windows上的PHP7 UTF-8文件名,由ZipArchive引起的新现象

Windows上的PHP7 UTF-8文件名,由ZipArchive引起的新现象
EN

Stack Overflow用户
提问于 2016-05-10 12:23:11
回答 1查看 1.4K关注 0票数 6

更新:

准备一份bug报告给那些让PHP 7成为可能的人,我再次修改了我的研究,并试图把它简化成几行简单的代码。在进行此操作时,我发现PHP本身并不是问题的原因。等我做完我会在这里分享我的结果。只是为了让你知道,而且不可能浪费你的时间什么的:)

概要: PHP7现在似乎能够编写UTF-8文件名,但无法访问它们?

序言:我在这里读到了大约10-15篇涉及这个主题的文章,但它们并没有帮助我解决这个问题,而且它们都比PHP7版本更古老。在我看来,这可能是一个新的问题,我不知道它是否可能是一个错误。我花了很多时间尝试对字符串进行en/解码,并试图找到一种使其工作的方法,但没有结果。

大家好,来自德国的问候(在这里插入害羞而不是我的母语),我希望你能帮助我解决这个我遇到的新现象。在PHP 7中,它似乎是“新的”。

我认为大多数在Windows系统上使用PHP的人都非常熟悉文件名的问题,以及管理对具有非ASCII文件名(或windows-1252或任何系统代码页)的文件的访问的PHP透明包装器。

我不太清楚该如何处理这个问题,正如你所看到的,我在作题方面经验不足,所以请不要马上把我的头扯下来。是的,我会努力保持简短。我们开始:

第一个症状:在更新到PHP7之后,我有时会遇到访问由我的软件生成的文件的问题。有时它像往常一样工作,有时不起作用。我发现不同之处在于,PHP7现在似乎能够编写UTF-8文件名,但无法使用这些名称访问文件。

在两个独立的“相同”系统(仅在PHP版本中不同)上生成上述文件之后,硬盘上的文件就是这样命名的:

PHP5.5: Lokaltest_KG_漢字_汉字_Krümhold-DEZ1604-140081-complete.zip

PHP 7: Lokaltest_KG_漢字_汉字_Krümhold 1604-140081-完备.PHP

出色的是,PHP 7能够在HDD上编写unicode文件名,而UTF-16则可以在windows afaik上使用。现在的缺点是,当我尝试访问这些文件时,例如使用is_file(),PHP5.5是有效的,但是PHP7却不行。

考虑一下这个代码片段(注意:我“黑掉”了这个函数,因为它是最简单的方式,不是为此目的编写的)。在生成zip文件后调用此函数,获取客户的名称和其他值以确定正确的名称。从数据库里出来的。PHP的数据库和内部编码都是UTF-8.clearstatcache本身并不是必要的,但我加入它是为了让事情变得更清楚。:所有发生的事情都是用PHP7完成的,没有其他实体负责创建zip文件。准确地说,这是用class ZipArchive完成的。实际上,即使是压缩存档也无关紧要,关键是文件名和文件内容都是由PHP7成功创建的。

代码语言:javascript
复制
public static function downloadFileAsStream( $file )
{
    clearstatcache();
    print $file . "<br/>";
    var_dump(is_file($file));
    die();
}       

产出如下:

代码语言:javascript
复制
D:/htdocs/otm/.data/_tmp/Lokaltest_KG_漢字_汉字_Krümhold-DEZ1604-140081-complete.zip
bool(false) 

因此,PHP7能够生成文件--它们确实存在于硬盘上,并且是合法的、可访问的和所有的--但是无法访问它们。is_file不是唯一失败的函数,例如file_exists()也会失败。

通过一个编码转换的小实验,让您体验一下我尝试过的一些东西:

代码语言:javascript
复制
public static function downloadFileAsStream( $file )
{
    clearstatcache();
    print $file . "<br/>";
    print mb_detect_encoding($file, 'ASCII,UTF-16,windows-1252,UTF-8', false) . "<br/>";
    print mb_detect_encoding($file, 'ASCII,UTF-16,windows-1252,UTF-8', true) . "<br/>";

    if (($detectedEncoding = mb_detect_encoding($file, 'ASCII,UTF-16,windows-1252,UTF-8', true)) != 'windows-1252')
    {
        $file = mb_convert_encoding($file, 'UTF-16', $detectedEncoding);
    }

    print $file . "<br/>";
    var_dump(is_file($file));
    die();
}       

产出如下:

代码语言:javascript
复制
D:/htdocs/otm/.data/_tmp/Lokaltest_KG_漢字_汉字_Krümhold-DEZ1604-140081-complete.zip
UTF-8
UTF-8
D:/htdocs/otm/.data/_tmp/Lokaltest_KG_o"[W_lI[W_Kr�mhold-DEZ1604-140081-complete.zip
NULL 

因此,从UTF-8 (数据库/内部编码)转换到UTF-16 (windows文件系统)似乎也不起作用。

我在这里束手无策,不幸的是,这个问题对我们来说非常重要,因为我们不能用这个问题来更新我们的系统。我希望有人能对这件事有所了解。不好意思,太长了,我不知道我能不能把我的观点说清楚。

加法:

代码语言:javascript
复制
$file = utf8_decode($file);
var_dump(is_file($file));
die();

传递假的文件名与日本字母。当我更改用于创建文件名的输入,使文件名现在为Lokaltest_KG_Krümhold-DEZ1604-140081-complete.zip时,上面的代码将传递真。那么,utf8_decode只对一小部分unicode,德国货币有帮助吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-05-11 16:48:46

在这里回答我自己的问题:真正的坏男孩是组件ZipArchive,它用错误编码的文件名创建文件。我写了一个有希望有帮助的bug报告:https://bugs.php.net/bug.php?id=72200

考虑一下这个简短的脚本:

代码语言:javascript
复制
print "php default_charset: ".ini_get('default_charset')."\n"; // just 4 info (UTF-8)

$filename = "bugtest_müller-lüdenscheid.zip"; // just an example
$filename = utf8_encode($filename); // simulating my database delivering utf8-string

$zip = new ZipArchive();
if( $zip->open($filename, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true )
{
    $zip->addFile('bugtest.php', 'bugtest.php'); // copy of script file itself
    $zip->close();
}

var_dump( is_file($filename) );  // delivers ?

产出:

代码语言:javascript
复制
output PHP 5.5.35:
    php default_charset: UTF-8
    bool(true)

output PHP 7.0.6:
    php default_charset: UTF-8
    bool(false)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37138463

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档