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

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

ただいまの
回答率

87.49%

move_uploaded_file パーミッションエラー

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 3,640

score 29

 前提・実現したいこと

phpを用いて画像を投稿して、保存できるサイトを作っています。
パーミッションエラーで画像が保存されないので、保存できるようにしたいです。
助言を頂けると、助かります。

 発生している問題・エラーメッセージ

Warning: move_uploaded_file(/var/www/html/phplesson2/images/1523413069_49741aaa3f531bf1034ffadb55d76bd9e68cd3dd.jpg): failed to open stream: Permission denied in /var/www/html/phplesson2/ImageUploader.php on line 67
Warning: move_uploaded_file(): Unable to move '/tmp/phphRQ8qn' to '/var/www/html/phplesson2/images/1523413069_49741aaa3f531bf1034ffadb55d76bd9e68cd3dd.jpg' in /var/www/html/phplesson2/ImageUploader.php on line 67

 該当のソースコード

<?php
    ini_set('display_errors', 1);
    define('MAX_FILE_SIZE', 1 * 1024 * 1024); //1MB
    define('THUMBNAIL_WIDTH', 400);
    define('IMAGES_DIR', __DIR__ . '/images');
    define('THUMBNAIL_DIR', __DIR__ . '/thumbs');

    if(!function_exists('imagecreatetruecolor')) {
        echo 'GD not installed';
        exit;
    }

    function h($s) {
        return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
    }

    require 'ImageUploader.php';

    $uploader = new \MyApp\ImageUploader();

    if($_SERVER['REQUEST_METHOD'] === 'POST') {
        $uploader->upload();
    }

?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Image Uploader</title>
    <style>
    body {
        text-align: center;
        font-family: Arial, sans-serif;
    }
    </style>
</head>
<body>

    <form action="" method="post" enctype="multipart/form-data">
        <input type="hidden" name="MAX_FILE_SIZE" value="<?php 
        echo h(MAX_FILE_SIZE); ?>">
        <input type="file" name="image">
        <input type="submit" value="upload">
    </form>
</body>
</html>
<?php

namespace MyApp;

class ImageUploader {

    private $_imageFileName;

    public function upload() {
        try {
            //error check
            $this->_validateUpload();

            //type check
            $ext = $this->_validateImageType();

            //save
            $this->_save($ext);

        }catch(\Exception $e) {
            echo $e->getMessage();
            exit;
        }
        //redirect
        header('Location: http://' . $_SERVER['HTTP_HOST']);
        exit;
    }

    private function _validateUpload() {
        if(!isset($_FILES['image']) || !isset($_FILES['image']['error'])) {
            throw new \Exception('Upload Error!');
        }

        switch($_FILES['image']['error']) {
            case UPLOAD_ERR_OK:
                return true;
            case UPLOAD_ERR_INI_SIZE:
            case UPLOAD_ERR_FORM_SIZE:
                throw new \Exception('File too large!');
            default:
                throw new \Exception('Err: ' . $_FILES['image']['error']);
        }
    }

    private function _validateImageType() {
        $imageType = exif_imagetype($_FILES['image']['tmp_name']);
        switch($imageType) {
            case IMAGETYPE_GIF:
                return 'gif';
            case IMAGETYPE_JPEG:
                return 'jpg';
            case IMAGETYPE_PNG:
                return 'png';
            default :
                throw new \Exception('PNG/JPEG/GIF only!');
        }
    }

    private function _save($ext) {
        $this->_imageFileName = sprintf(
            '%s_%s.%s',
            time(),
            sha1(uniqid(mt_rand(), true)),
            $ext
        );
        $savePath = IMAGES_DIR . '/' . $this->_imageFileName;
        $res = move_uploaded_file($_FILES['image']['tmp_name'], $savePath);
        if($res === false) {
            throw new \Exception('Could not upload!');
        }

    }

}

 試したこと

imagesディレクトリの所有者をapacheにしました。
imagesディレクトリの権限を777にしました。
/tmpディレクトリの権限を777にしたり所有者をapacheにしたり、一般ユーザーにしたりしました。

 補足情報(FW/ツールのバージョンなど)

CentOS Linux release 7.4.1708 (Core) 
Server version: Apache/2.4.6 (CentOS)
PHP 5.6.35 

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

とりあえずmove_uploaded_fileではなく
所定のIMAGES_DIRに対してfopen~fwrite~fcloseで
ファイルが書き込めるかどうか確認してみるとよいでしょう

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/04/11 15:25

    回答どうもありがとうございます。
    言われた通りのことをしてみたところ、書き込みだけできていなかったので、他に原因がありそうだと思いました。
    結局はCentOSのセキュリティレベル-SELinuxをEnforcingから無効にすることで、通るようになりました。
    しかしこれはセキュリティ的にどうなんでしょうか。
    もしよろしければ返信をくださるとうれしいです。

    キャンセル

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

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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