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

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

新規登録して質問してみよう
ただいま回答率
85.48%
CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

PHP

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

Q&A

解決済

2回答

11838閲覧

phpで日本語名のファイルをアップロードするとファイルが壊れる

alberorana

総合スコア52

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

PHP

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

1グッド

2クリップ

投稿2017/07/10 02:24

###前提・実現したいこと
PHPであるユーザーがアップロードしたファイルを他人がダウンロードできるWebアプリを作っています。
拡張子はpdf,xlsm,docxあたりを対象として、日本語もOKにしたいです。

###発生している問題・エラーメッセージ
問題になっているのは、日本語名のファイルをアップロードするとファイルが壊れ、文字化けしてしまうことです。詳細として

・日本語名のファイルをアップロードすると0バイトとなり開くことができない
・ダウンロードログとしてMysqlにダウンロードされたファイル名を挿入していますが、ファイル名が文字化けしてしまう。
この2点になります。

ファイル破損

ダウンロードログ文字化け

###該当のソースコード
こちらがアップロードのソースコード。
プログラムの都合上、一度自前の一時フォルダに移動→本来の保管場所という方法をとっています。

まずはユーザーから自前の一時フォルダへのアップロード

php

1<?php 2session_start(); 3$uploaddir = $_SESSION['uploaddir'];//前ページで決めたディレクトリを引き継ぎ(root/UID/samba/nsr) 4$ds = DIRECTORY_SEPARATOR; //スラッシュの変数 5require('dbc.php'); 6$cookie = $_COOKIE['cookie']; 7$stmt = $pdo -> prepare("SELECT * FROM user WHERE cookie=:cookie"); 8$stmt -> bindValue(':cookie', $cookie, PDO::PARAM_STR); 9$stmt -> execute(); 10$udata = $stmt -> fetch(); 11$pdo = NULL; 12 13if (!empty($_FILES)) {//アップロードファイルがある時の処理 14 15 $tempFile = $_FILES['file']['tmp_name']; //3 16 //一時保管ディレクトリ 17 $tmpdir = '/home/tmp/' . $udata['uid']; 18 //ディレクトリの存在確認 19 if(!file_exists($tmpdir)){ 20 mkdir($tmpdir, 0700); 21 } 22 $_SESSION['tmpdir'] = $tmpdir; 23 $tmpxml = $tmpdir . '/' . $_FILES['file']['name']; //5 24 $_SESSION['tmpxml'] = $tmpxml; 25 move_uploaded_file($tempFile,$tmpxml); 26 27} 28?>

次に一時フォルダから本フォルダへ

php

1<?php 2require('../library/functions.php');//共通宣言、関数呼び出し 3require('../dbc.php');//データベース接続 4$cookie = $_COOKIE['cookie']; 5$stmt = $pdo -> prepare("SELECT * FROM user WHERE cookie=:cookie"); 6$stmt -> bindValue(':cookie', $cookie, PDO::PARAM_STR); 7$stmt -> execute(); 8$udata = $stmt -> fetch(); 9$pdo = NULL; 10$tmppass = '/home/tmp/' . $udata['uid'] . '/'; 11//ディレクトリの中身を検索 12$dir_content = scandir($tmppass, 1);//ディレクトリ内検索 13$loop = count($dir_content); 14$loop = $loop - 2; 15//アップロードボタンが押されたら 16if(isset($_POST['upload'])){ 17 $uploaddir = $_SESSION['uploaddir'];//アップロードフォルダを定義 18 $handle = opendir( $tmppass ) ;//tmpフォルダの中身をすべて解析 19 while (false !== ($entry = readdir($handle))) { 20 if ($entry != "." && $entry != "..") { 21 //tmpディレクトリにファイルがある限りユーザーディレクトリへ移動する 22 rename($tmppass . '/' . $entry, $uploaddir . '/' . $entry); 23 } 24 } 25 unlink_dir($tmppass); 26 header("Location: /parts/regist_fin.php"); 27 exit(); 28} 29include($_SERVER['DOCUMENT_ROOT'] . '/parts/head.php'); 30?> 31 </head> 32 <body class="index"> 33 <h1>DOC-FINDER-V1</h1> 34 <div class="container"> 35 <h2>アップロードファイルの確認</h2> 36 <p>アップロードするファイルに間違いがなければアップロードボタンを押してください。</p> 37 <?php 38 $i = 0; 39 while ($i < $loop) { 40 echo '<p>' . $dir_content["$i"] . '</p>'; 41 $i++; 42 }//ファイルの数だけループ 43 ?> 44 <div class='row'> 45 <div class="col-md-offset-4 col-md-4"> 46 <form action="" method="post" enctype='multipart/form-data' multiple><input class="btn btn-warning" type="submit" name="upload" value="アップロード"></form> 47 </div> 48 <div class="col-md-2"> 49 <input type="button" class="btn btn-danger" value="キャンセル" onClick="location.href='/parts/up_cancel.php'"> 50 </div> 51 </div> 52 </div><!-- class container --> 53 </body>

ダウンロードロジック

php

1<?php 2session_start(); 3require('dbc.php'); 4$cookie = $_COOKIE['cookie']; 5$stmt = $pdo -> prepare("SELECT * FROM user WHERE cookie=:cookie"); 6$stmt -> bindValue(':cookie', $cookie, PDO::PARAM_STR); 7$stmt -> execute(); 8$udata = $stmt -> fetch(); 9$pdo = NULL; 10 11$uid = $udata['uid']; 12$recordnumber = $_SESSION['id']; 13 14$dir = $_SESSION['dir']; 15$url = $_SERVER["REQUEST_URI"]; 16$keys = parse_url($url); //パース処理 17$path = explode("/", $keys['path']); //分割処理 18$file = end($path); //最後の要素を取得 19$file = mb_convert_encoding($file, "UTF-8", "auto"); 20$fpath = $dir . '/' . $file; 21header('Content-Length: '.filesize($fpath)); 22header("Content-type: application/octet-stream"); 23header('Content-disposition: attachment; filename="'.$file.'"'); 24readfile($fpath); 25//ダウンロードテーブルに挿入 26require('dbc.php'); 27$stmt = $pdo -> prepare("INSERT INTO download(uid,file,recordnumber) VALUES(:uid,:file,:recordnumber)"); 28$stmt -> bindValue(':uid', $uid, PDO::PARAM_STR); 29$stmt -> bindValue(':file', $file, PDO::PARAM_STR); 30$stmt -> bindValue(':recordnumber', $recordnumber, PDO::PARAM_INT); 31$stmt -> execute(); 32$pdo = NULL; 33?> 34

###試したこと
・utf-8への変換
・日本語、アルファベットの切り分け→日本語ファイルのみ破損、英語ファイルは文字化け、破損しない

###補足情報(言語/FW/ツール等のバージョンなど)
・php 7.0.19
・CentOS6.8
開発環境はローカル上のVMに構築しています。

以上になります。原因がわからなくて困っています。
何卒よろしくお願いいたします。

ikuwow👍を押しています

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

文字コードを統一していますか?

HTMLの頭の部分が無いので分からないのですが、UTF-8に統一しましょう。
その上でアップロードしてきたファイルを受け取った時に、$_FILESの配列をvar_dumpで見て、
ちゃんと文字コードがUTF-8になっているか確認しましょう。

header("Content-type: text/plain; charset=UTF-8"); var_dump($_FILES); exit;

MySQLの文字コードはUTF-8になっていますか?
こちらも確認しないと化ける原因になります。

ダウンロード時に文字コードを設定していますか?

php

1header('Content-Disposition: attachment; filename*=UTF-8\'\''.rawurlencode($filename)); 2```このようの指定しないと、クライアントで文字化けします。 3 4Macが入ると、濁点・半濁点入りのファイル名がおかしくなります。 5[Unicodeの正規化](https://jw7.org/2015/09/07/php-mac-filename/) 6 7このあたりをすべて確認しましょう。

投稿2017/07/10 14:44

shi_ue

総合スコア4437

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

日本語ファイル名を利用する限りトラブルはさけられません。
またファイル一覧を表示して直接リンクをはるような運用でなければ
直接ファイル名を日本語にする意味はないと思います。
URLエンコードしたような名称で管理してはいけないでしょうか?

投稿2017/07/10 03:18

yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問