###前提・実現したいこと
PHPであるユーザーがアップロードしたファイルを他人がダウンロードできるWebアプリを作っています。
拡張子はpdf,xlsm,docxあたりを対象として、日本語もOKにしたいです。
###発生している問題・エラーメッセージ
問題になっているのは、日本語名のファイルをアップロードするとファイルが壊れ、文字化けしてしまうことです。詳細として
・日本語名のファイルをアップロードすると0バイトとなり開くことができない
・ダウンロードログとしてMysqlにダウンロードされたファイル名を挿入していますが、ファイル名が文字化けしてしまう。
この2点になります。
###該当のソースコード
こちらがアップロードのソースコード。
プログラムの都合上、一度自前の一時フォルダに移動→本来の保管場所という方法をとっています。
まずはユーザーから自前の一時フォルダへのアップロード
php
<?php session_start(); $uploaddir = $_SESSION['uploaddir'];//前ページで決めたディレクトリを引き継ぎ(root/UID/samba/nsr) $ds = DIRECTORY_SEPARATOR; //スラッシュの変数 require('dbc.php'); $cookie = $_COOKIE['cookie']; $stmt = $pdo -> prepare("SELECT * FROM user WHERE cookie=:cookie"); $stmt -> bindValue(':cookie', $cookie, PDO::PARAM_STR); $stmt -> execute(); $udata = $stmt -> fetch(); $pdo = NULL; if (!empty($_FILES)) {//アップロードファイルがある時の処理 $tempFile = $_FILES['file']['tmp_name']; //3 //一時保管ディレクトリ $tmpdir = '/home/tmp/' . $udata['uid']; //ディレクトリの存在確認 if(!file_exists($tmpdir)){ mkdir($tmpdir, 0700); } $_SESSION['tmpdir'] = $tmpdir; $tmpxml = $tmpdir . '/' . $_FILES['file']['name']; //5 $_SESSION['tmpxml'] = $tmpxml; move_uploaded_file($tempFile,$tmpxml); } ?>
次に一時フォルダから本フォルダへ
php
<?php require('../library/functions.php');//共通宣言、関数呼び出し require('../dbc.php');//データベース接続 $cookie = $_COOKIE['cookie']; $stmt = $pdo -> prepare("SELECT * FROM user WHERE cookie=:cookie"); $stmt -> bindValue(':cookie', $cookie, PDO::PARAM_STR); $stmt -> execute(); $udata = $stmt -> fetch(); $pdo = NULL; $tmppass = '/home/tmp/' . $udata['uid'] . '/'; //ディレクトリの中身を検索 $dir_content = scandir($tmppass, 1);//ディレクトリ内検索 $loop = count($dir_content); $loop = $loop - 2; //アップロードボタンが押されたら if(isset($_POST['upload'])){ $uploaddir = $_SESSION['uploaddir'];//アップロードフォルダを定義 $handle = opendir( $tmppass ) ;//tmpフォルダの中身をすべて解析 while (false !== ($entry = readdir($handle))) { if ($entry != "." && $entry != "..") { //tmpディレクトリにファイルがある限りユーザーディレクトリへ移動する rename($tmppass . '/' . $entry, $uploaddir . '/' . $entry); } } unlink_dir($tmppass); header("Location: /parts/regist_fin.php"); exit(); } include($_SERVER['DOCUMENT_ROOT'] . '/parts/head.php'); ?> </head> <body class="index"> <h1>DOC-FINDER-V1</h1> <div class="container"> <h2>アップロードファイルの確認</h2> <p>アップロードするファイルに間違いがなければアップロードボタンを押してください。</p> <?php $i = 0; while ($i < $loop) { echo '<p>' . $dir_content["$i"] . '</p>'; $i++; }//ファイルの数だけループ ?> <div class='row'> <div class="col-md-offset-4 col-md-4"> <form action="" method="post" enctype='multipart/form-data' multiple><input class="btn btn-warning" type="submit" name="upload" value="アップロード"></form> </div> <div class="col-md-2"> <input type="button" class="btn btn-danger" value="キャンセル" onClick="location.href='/parts/up_cancel.php'"> </div> </div> </div><!-- class container --> </body>
ダウンロードロジック
php
<?php session_start(); require('dbc.php'); $cookie = $_COOKIE['cookie']; $stmt = $pdo -> prepare("SELECT * FROM user WHERE cookie=:cookie"); $stmt -> bindValue(':cookie', $cookie, PDO::PARAM_STR); $stmt -> execute(); $udata = $stmt -> fetch(); $pdo = NULL; $uid = $udata['uid']; $recordnumber = $_SESSION['id']; $dir = $_SESSION['dir']; $url = $_SERVER["REQUEST_URI"]; $keys = parse_url($url); //パース処理 $path = explode("/", $keys['path']); //分割処理 $file = end($path); //最後の要素を取得 $file = mb_convert_encoding($file, "UTF-8", "auto"); $fpath = $dir . '/' . $file; header('Content-Length: '.filesize($fpath)); header("Content-type: application/octet-stream"); header('Content-disposition: attachment; filename="'.$file.'"'); readfile($fpath); //ダウンロードテーブルに挿入 require('dbc.php'); $stmt = $pdo -> prepare("INSERT INTO download(uid,file,recordnumber) VALUES(:uid,:file,:recordnumber)"); $stmt -> bindValue(':uid', $uid, PDO::PARAM_STR); $stmt -> bindValue(':file', $file, PDO::PARAM_STR); $stmt -> bindValue(':recordnumber', $recordnumber, PDO::PARAM_INT); $stmt -> execute(); $pdo = NULL; ?>
###試したこと
・utf-8への変換
・日本語、アルファベットの切り分け→日本語ファイルのみ破損、英語ファイルは文字化け、破損しない
###補足情報(言語/FW/ツール等のバージョンなど)
・php 7.0.19
・CentOS6.8
開発環境はローカル上のVMに構築しています。
以上になります。原因がわからなくて困っています。
何卒よろしくお願いいたします。
まだ回答がついていません
会員登録して回答してみよう