スレッド表示 | フラット表示〕 全トピック 920 件中 56 番目 次≫ ≪前

ファイルダウンロードの文字化け

created: 2008-04-23 16:30 | modified: 2008-04-24 10:47 | reply: 4

[4146] ファイルダウンロードの文字化け

user: たか | created: 2008-04-23 16:30
たかと申します

phpにてファイルのアップローダーを作成しました。
簡単な仕様としては

1.ユーザがファイルをアップロードする
2.受け取りの担当者へダウンロードページのリンク付きのメールが届く
3.受取り担当者はリンクからダウンロードページへ行く
4.ダウンロードボタンを押すとファイルのダウンロードを実行する。

3までは問題なく動作するのですが、4で不具合があります。
win,MacのIEでは文字化けなくダウンロード出来るが、Mac safariの場合
ダウンロードしたファイル名が文字化けしている。
(日本語以外は正しく表示されます)

解決策を見出せずにいます・・・
ご教授頂けないでしょうか

【サーバ環境】
FreeBSD6.2
php5

【クライアントテスト環境】
winXP SP2 IE6
Mac OS X safari 1.3.2

ダウンロードスクリプト
(ダウンロードボタンを押した際に動くスクリプト)
 $dlname,$dltype,$dlsizeはダウンロードリンクのアドレスに情報を持たせてあります

-------------------------------
<?
header("Content-Type: text/html; charset=EUC-JP");
$dlpath = "./data/";
$dlname = $_GET{'fn'};
$dlpathname = "$dlpath$dlname";
$dltype = $_GET{'ft'};
$dlsize = $_GET{'fs'};

$covname = mb_convert_encoding($dlname,"SJIS","EUC-JP");

if (file_exists($dlpathname)){
header("Content-type: {$dltype}; charset=SJIS");
header("Content-Disposition: attachment; filename={$covname}");
header("Content-Transfer-Encoding: binary");
header("Content-Length: {$dlsize}");
readfile($dlpathname);

}else{
print "ダウンロードするファイルがありません。";
exit();

}
exit();
?>
reply: 4147 返信 編集 削除

[4147] ダウンロード時にファイル名の文字化け

user: ゆうじ | created: 2008-04-23 18:45
こんばんわ。

ヘッダにマルチバイト文字が入ってもいいのかな?
日本語を含むレスポンスヘッダをどのクライアントも
都合よく解釈してくれるとは思えませんので
原因はこのあたりだろうと思います。

ダウンロード処理ってほとんどやったことがなくて
うまくいくかわかりませんが一度これを試してみてください。

$covname = mb_convert_encoding($dlname,"SJIS","EUC-JP");
$covname = urlencode($covname); // 追記


あと、ファイル形式が何であれダウンロードするなら
Content-Type は application/octet-stream でいけると思います。
header('Content-Type: application/octet-stream');


# 本題とは関係ありませんが、
# $_GET で得られる値はユーザが自由に書き換えられるので
# 以下についてはダウンロードするスクリプト側で
# 初期化する仕様の方がいいと思います。
#
# $dltype = $_GET{'ft'};
# $dlsize = $_GET{'fs'};


#追記:
始めの header("Content-Type: text/html; charset=EUC-JP");
いらない気がします。 これが原因かも。

また、SJIS はPHPだけ通用する表記です。
charset を指定する時は Shift_JIS を使いましょう。
Parent: 4146  reply: 4148 返信 編集 削除

[4148] ありがとう御座います

user: たか | created: 2008-04-23 19:34
さっそくのアドバイスありがとう御座います。
本日帰宅してしまいましたので、アドバイスを元に明日テストしてみます

当方、初めてのphpでいろいろサンプル見ながら作っていましたので
おかしな所が多数あるかもしれません(汗)

さっそくですが、下記の部分どこかで見かけたので試してみましたが
駄目でした・・・
> $covname = mb_convert_encoding($dlname,"SJIS","EUCJP");
> $covname = urlencode($covname); // 追記

ファイル形式についても、これより前のスクリプトで情報取得する必要
があったので、変数に入れて使いまわしていたのですが、変えてテスト
してみます。

> #追記:
> 始めの header("Content-Type: text/html; charset=EUC-JP");
> いらない気がします。 これが原因かも。

これも外してテストしてみます


> # 本題とは関係ありませんが、
> # $_GET で得られる値はユーザが自由に書き換えられるので
> # 以下についてはダウンロードするスクリプト側で
> # 初期化する仕様の方がいいと思います。
> #
> # $dltype = $_GET{'ft'};
> # $dlsize = $_GET{'fs'};

私の知識不足の為、ここがいまいち理解できません・・・・
よろしければ、詳しく教えてください
よろしくお願いします


> また、SJIS はPHPだけ通用する表記です。
> charset を指定する時は Shift_JIS を使いましょう。

これも勉強になります。早速変更してみます
ありがとう御座います
Parent: 4147  reply: 4149 返信 編集 削除

[4149] ダウンロードのサンプルコード

user: ゆうじ | created: 2008-04-24 01:26
検索してみましたがどこを見ても解決策はみつかりませんでした。
Safari で日本語ファイル名のファイルをダウンロードすれば
文字化けするものという前提で、任意のASCII文字に
置き換えたりしてる対処策ものばかりでした。

Safari がファイル名のエンコーディング検出を
間違っているのが原因だとするとサーバ側で対処は無理かもしれませんね。

まあ、いい機会なのでダウンロードのサンプルコードを書いてみました。
$DownloadName の初期化や Content-type: のあたりに
コメントアウトしたコードがありますので試してみてください。


> # 本題とは関係ありませんが、
これについては、サンプルにコードを書いてますし
このページにかいてますのでご覧頂ください。
http://www.sound-uz.jp/php/note/securGPC

<?php
/**
* ファイル名は $_GET['fn'] で得られるものとする。
* 内部エンコーディングは EUC-JP とする
*/

/**
* ファイル名の検証(バリデーション)
* 必ず想定内の値か確認
*/
if (!isset($_GET['fn']) || !strlen($_GET['fn'])) {
exit(); // $_GET['fn']が空
}
if (preg_match('/[[:control:]]/', $_GET['fn'])) {
exit(); // 制御コードを含んでいる
}
if (strlen($_GET['fn']) != strlen(basename($_GET['fn']))) {
exit(); // ファイル名の他にパス情報を含んでいる
}

/**
* ファイル名のエンコーディング検出
* & $fileName の初期化
*/
$encoding = mb_detect_encoding($_GET['fn']);
if ('ASCII' != $encoding && 'EUC-JP' !== $encoding) {
$fileName = mb_convert_encoding($_GET['fn'], 'EUC-JP', $encoding);
} else {
$fileName = $_GET['fn'];
}

/**
* ダウンロード元ディレクトリ
* 予め決まってるはずなので相対パスの必要が無ければフルパスを記述
*/
$basedir = '/home/username/htdocs/data/';

/**
* ファイルのパス
*/
$FilePath = $baseDir.$fileName;

/**
* ファイルの有無と読み込み可能か確認
*/
if (!is_file($FilePath) && !is_readable($FilePath)) {
exit();
}

/**
* ファイルサイズ獲得
*/
$Length = filesize($FilePath);

/**
* ダウンロードファイル名を初期化
*
* $_SERVER['HTTP_USER_AGENT'] に 'MSIE' が含まれていれば
* InternetExplorer と判定し Shift_JIS にエンコード変換。
* それ以外は UTF-8 で試してみる。
*/
if (preg_match('/MSIE/', $_SERVER['HTTP_USER_AGENT'])) {
// IEはShift_JISでいけてるようなので
$DownloadName = mb_convert_encoding($fileName, 'SJIS', 'EUC-JP');
} else {
$DownloadName = mb_convert_encoding($fileName, 'UTF-8', 'EUC-JP');
// $DownloadName = urlencode($DownloadName);
}

/**
* ファイルを出力
*/

// 存在しない Content-type を指定することで、
// ファイルの処理方法の確認ダイアログを
// ブラウザが出してくれる事を期待しての application/octet-stream-dammy
// また name を指定するといけるブラウザもあるらしい。
header('Content-type: application/octet-stream-dammy; name='. $DownloadName);
//header('Content-type: application/octet-stream-dammy');
//header('Content-type: application/octet-stream');
// ファイル名を " で囲ってみるとかどうでしょう
//header('Content-type: application/octet-stream-dammy; name="'. $DownloadName. '"');

// ココで指定する charset はファイルそのものの文字セットで
// ファイル名ではないので、ダウンロード時には不要かと思います。
header('Content-Disposition: attachment; filename='. $DownloadName);
//header('Content-Disposition: attachment; filename="'. $DownloadName. '"');

header('Content-Length: '. $Length);

readfile($FilePath);

?>
Parent: 4148  reply: 4150 返信 編集 削除

[4150] 報告です

user: たか | created: 2008-04-24 10:47
サンプルコードありがとうございます。
大変参考になりました。

今朝より、サンプルコードを使用させて頂いたり、オリジナルに
サンプルコードを参考に修正を加えたり、色々やってみましたが
問題は解決しませんでした・・・

ファイル名をShift-JISに変換したものとUTF-8に変換したもので日本語の
置き換わり方は違うので、そこら辺りには問題ないような気がします・・・
ダウンロードさせる際のheaderの書き方を色々試したりして気長に頑張って
みます。
Parent: 4149  返信 編集 削除
スレッド表示 | フラット表示〕 全トピック 920 件中 56 番目 次≫ ≪前
ページの一番上へ
Googleグックマークに登録 Yahooグックマークに登録 livedoorクリップに登録 @niftyクリップに登録 はてなブックマークに登録 deliciousに登録 Buzzurlに登録 FC2ブックマークに登録
最近更新された掲示板トピックス
管理人Blog
Yahoo Search

最近更新したNote
PHPマニュアル
今日のブックマーク
PHPマニュアル関数検索
関数名を入力し検索ボタンをクリック↑