質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.32%

  • PHP

    21359questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • 文字コード

    214questions

    文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

  • zip

    62questions

    ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。

PHPのZipArchive::statIndexで日本語画像ファイルを扱うと文字化けする

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 7,726

環境

CentOS6.6
PHP5.5系
CodeIgniter2.2系

要件

PHPにてWebフォームを作成。Zipアーカイブをフォームよりアップロードして、
中に含まれる日本語ファイル名のjpgファイルをサーバ上に展開したい。

不具合内容

下記プログラムにてZIPを処理しています。

プログラム(必要箇所のみ抜粋)
private function extractTo($zip_src, $to_enc = 'UTF-8', $from_enc = 'CP932')
{
    $zip = new ZipArchive();

    $num_files = $zip->numFiles;
    for ($i = 0; $i < $num_files; $i++)
    {
        $stat = $zip->statIndex($i);
//var_dump($stat['name'], mb_detect_encoding($stat['name']));
        $name = mb_convert_encoding($stat['name'], $to_enc, $from_enc);
    }
//exit;
    $zip->close();
}

PHP標準のZipArchiveクラスのstatIndexメソッドにてZIPファイルから画像ファイルを読み込んでいるのですが、
var_dump($stat['name'], mb_detect_encoding($stat['name']));
すると、下記の出力が得られる状態です。

問題がない環境(Aとする)
string(28) "zip/???????W????.jpg"
string(4) "SJIS"
string(42) "zip/??????????????????????.jpg"
string(4) "SJIS"
string(30) "zip/???????????.jpg"
string(4) "SJIS"

不具合の発生する環境(Bとする)
string(41) "zip/eoe„¢e?aWaaaC.jpg"
string(5) "UTF-8"
string(75) "zip/e„ eƒÑeƒ³e?e?e?uOe„£e„¨e?eƒ³aƒÐiÊ.jpg"
string(5) "UTF-8"
string(47) "zip/eƒ¶e}e?e}e„¦e!e?.jpg"
string(5) "UTF-8"

いずれの環境もこの時点では文字化けしていますが、
直後にmb_convert_encodingすることで対処しています。

B環境にてstatIndexした時点ですでにUTF-8として読み込まれていることが、直接の原因と考えています。

質問内容

上記の根本原因として、サーバ環境間になにかしらの差異があるもとと考えています。
こういった事象に近いご経験ある方に、その差異がどういった設定なのかということをご教示いただければと思います。
確認済みの事項とを以下に記載します。

確認済み事項

localeコマンドの出力結果(両環境で差異なし)
LANG=ja_JP.UTF-8
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=

参考記事にあるとおり、PHP標準の関数、クラスはOSのロケール設定が影響してくる場合があるとのことでしたので、ロケール設定を確認しましたが、いずれの環境でも差異はありませんでした。


長文となりましたが、
どうぞよろしくお願いいたします。



追加情報①php.iniの差分
< ; The syntax of the file is extremely simple.  Whitespace and Lines
---
> ; The syntax of the file is extremely simple.  Whitespace and lines
85a86,87
> ; This is php.ini-production INI file.
> 
139,148d140
< ; session.bug_compat_42
< ;   Default Value: On
< ;   Development Value: On
< ;   Production Value: Off
< 
< ; session.bug_compat_warn
< ;   Default Value: On
< ;   Development Value: On
< ;   Production Value: Off
< 
200,206c192,197
< ; <? and ?> tags as PHP source which should be processed as such. It's been
< ; recommended for several years that you not use the short tag "short cut" and
< ; instead to use the full <?php and ?> tag combination. With the wide spread use
< ; of XML and use of these tags by other languages, the server can become easily
< ; confused and end up parsing the wrong code in the wrong context. But because
< ; this short cut has been a feature for such a long time, it's currently still
< ; supported for backwards compatibility, but we recommend you don't use them.
---
> ; <? and ?> tags as PHP source which should be processed as such. It is
> ; generally recommended that <?php and ?> should be used and that this feature
> ; should be disabled, as enabling it may result in issues when generating XML
> ; documents, however this remains supported for backward compatibility reasons.
> ; Note that this directive does not control the <?= shorthand tag, which can be
> ; used regardless of this directive.
375c366
< expose_php = On
---
> expose_php = Off
427c418
< ; E_ALL             - All errors and warnings (includes E_STRICT as of PHP 6.0.0)
---
> ; E_ALL             - All errors and warnings (includes E_STRICT as of PHP 5.4.0)
585c576
< ; Log errors to syslog (Event Log on NT, not valid in Windows 95).
---
> ; Log errors to syslog (Event Log on Windows).
731a723,726
> ; Directory where the temporary files should be placed.
> ; Defaults to the system default (see sys_get_temp_dir)
> ; sys_temp_dir = "/tmp"
> 
754c749
< ;cgi.redirect_status_env = ;
---
> ;cgi.redirect_status_env =
771c766
< ;fastcgi.impersonate = 1;
---
> ;fastcgi.impersonate = 1
800d794
< ;upload_max_filesize = 2M
958,967d951
< ; For Win32 only.
< ; http://php.net/smtp
< SMTP = localhost
< ; http://php.net/smtp-port
< smtp_port = 25
< 
< ; For Win32 only.
< ; http://php.net/sendmail-from
< ;sendmail_from = me@example.com
< 
982a967,968
> ; Log mail to syslog (Event Log on Windows).
> ;mail.log = syslog
1354c1340,1352
< session.save_path = "/var/lib/php/session"
---
> 
> ; RPM note : session directory must be owned by process owner
> ; for mod_php, see /etc/httpd/conf.d/php.conf
> ; for php-fpm, see /etc/php-fpm.d/*conf
> ;session.save_path = "/tmp"
> 
> ; Whether to use strict session mode.
> ; Strict session mode does not accept uninitialized session ID and regenerate
> ; session ID if browser sends uninitialized session ID. Strict mode protects
> ; applications from session fixation via session adoption vulnerability. It is
> ; disabled by default for maximum compatibility, but enabling it is encouraged.
> ; https://wiki.php.net/rfc/strict_sessions
> session.use_strict_mode = 0
1435,1460c1433
< ;          find /path/to/sessions -cmin +24 | xargs rm
< 
< ; PHP 4.2 and less have an undocumented feature/bug that allows you to
< ; to initialize a session variable in the global scope.
< ; PHP 4.3 and later will warn you, if this feature is used.
< ; You can disable the feature and the warning separately. At this time,
< ; the warning is only displayed, if bug_compat_42 is enabled. This feature
< ; introduces some serious security problems if not handled correctly. It's
< ; recommended that you do not use this feature on production servers. But you
< ; should enable this on development servers and enable the warning as well. If you
< ; do not enable the feature on development servers, you won't be warned when it's
< ; used and debugging errors caused by this can be difficult to track down.
< ; Default Value: On
< ; Development Value: On
< ; Production Value: Off
< ; http://php.net/session.bug-compat-42
< session.bug_compat_42 = Off
< 
< ; This setting controls whether or not you are warned by PHP when initializing a
< ; session value into the global space. session.bug_compat_42 must be enabled before
< ; these warnings can be issued by PHP. See the directive above for more information.
< ; Default Value: On
< ; Development Value: On
< ; Production Value: Off
< ; http://php.net/session.bug-compat-warn
< session.bug_compat_warn = Off
---
> ;          find /path/to/sessions -cmin +24 -type f | xargs rm
1597c1570
< mssql.compatability_mode = Off
---
> mssql.compatibility_mode = Off
1654,1678d1626
< [COM]
< ; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs
< ; http://php.net/com.typelib-file
< ;com.typelib_file =
< 
< ; allow Distributed-COM calls
< ; http://php.net/com.allow-dcom
< ;com.allow_dcom = true
< 
< ; autoregister constants of a components typlib on com_load()
< ; http://php.net/com.autoregister-typelib
< ;com.autoregister_typelib = true
< 
< ; register constants casesensitive
< ; http://php.net/com.autoregister-casesensitive
< ;com.autoregister_casesensitive = false
< 
< ; show warnings on duplicate constant registrations
< ; http://php.net/com.autoregister-verbose
< ;com.autoregister_verbose = true
< 
< ; The default character set code-page to use when passing strings to and from COM objects.
< ; Default: system ANSI code page
< ;com.code_page=
< 
1688c1636
< mbstring.internal_encoding = UTF-8 
---
> mbstring.internal_encoding = UTF-8
1692c1640
< mbstring.http_input = pass
---
> mbstring.http_input = UTF-8
1715c1663
< mbstring.substitute_character = none;
---
> mbstring.substitute_character = none
1729c1677
< mbstring.strict_detection = Off
---
> mbstring.strict_detection = On
1784a1733,1736
> 
> ; RPM note : cache directory must be owned by process owner
> ; for mod_php, see /etc/httpd/conf.d/php.conf
> ; for php-fpm, see /etc/php-fpm.d/*conf
1816a1769,1773
> [curl]
> ; A default value for the CURLOPT_CAINFO option. This is required to be an
> ; absolute path.
> ;curl.cainfo =
> 
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • KoichiSugiyama

    2015/05/27 14:03

    それぞれの環境のphp.iniは全く同じものを使用しているのでしょうか?

    キャンセル

  • kunichan_1985

    2015/05/27 15:02

    ご指摘ありがとうございます。diffの結果を追記いたしました。mbstringディレクティブで少々差分があるようですので、合わせて検証してみます。

    キャンセル

  • kunichan_1985

    2015/05/28 10:25

    B環境のphp.iniを以下のとおり修正、httpd再起動後に動作確認しましたが、変わらずでした。。
    ※その後念のためA環境のphp.iniをB環境に移してみましたが、やはりダメでした。
    ・mbstring.strict_detection = Off
    ・mbstring.http_input = pass

    その他現状で疑っているポイントとしましては、
    ・httpd.confの差異(B環境では不要なモジュールの多くをコメントアウトしているなどの差分がございます)
    などあるかなあと思っています。

    キャンセル

回答 1

checkベストアンサー

0

php.iniの差分を見る限り「mbstring.strict_detection(文字コードの自動判別)」がONかOFFかで結果が違ってきているのではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • PHP

    21359questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • 文字コード

    214questions

    文字コードとは、文字や記号をコンピュータ上で使用するために用いられるバイト表現を指します。

  • zip

    62questions

    ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。