🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
PHP

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

Q&A

解決済

2回答

1535閲覧

DBに画像をパスとしてアップしようとしたらエラーとなる(Warning: move_uploaded_file(): Unable to move )

Ms.yy

総合スコア83

PHP

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

0グッド

0クリップ

投稿2020/01/06 12:27

編集2020/01/06 12:30

前提・実現したいこと

 画像をパスとしてDBに入れたいのですが、ファイル選択後アップしようとしたらエラーとなります。
解決方法分かる方いらっしゃいましたらよろしくお願いします。

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

  Warning: move_uploaded_file(test/256b353c880efec6233f5cb3cebea7416ca19b19.jpg): failed to open stream: No such file or directory in /Applications/XAMPP/xamppfiles/htdocs/calendar_php/folio/test/index.php on line 66 Warning: move_uploaded_file(): Unable to move '/Applications/XAMPP/xamppfiles/temp/phpWFkIdu' to 'test/256b353c880efec6233f5cb3cebea7416ca19b19.jpg' in /Applications/XAMPP/xamppfiles/htdocs/calendar_php/folio/test/index.php on line 66

common.php

<?php /** * common.php */ /** * connect_db * @return \PDO */ function connect_db() { $dsn = 'mysql:host=localhost;dbname=mblog;charset=utf8'; $username = 'root'; $password = ''; $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION , PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; return new PDO($dsn, $username, $password, $options); } /** * insert * @param string $sql * @param array $arr * @return int lastInsertId */ function insert($sql, $arr = []) { $pdo = connect_db(); $stmt = $pdo->prepare($sql); $stmt->execute($arr); return $pdo->lastInsertId(); } /** * select * @param string $sql * @param array $arr * @return array $rows */ function select($sql, $arr = []) { $pdo = connect_db(); $stmt = $pdo->prepare($sql); $stmt->execute($arr); return $stmt->fetchAll(); } /** * htmlspecialchars * @param string $string * @return $string */ function h($string) { return htmlspecialchars($string, ENT_QUOTES, 'utf-8'); }

index.php

<?php /** * index.php */ /** * 共通関数読み込み */ require 'common.php'; /** * file_upload */ function file_upload() { // POSTではないとき何もしない if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') !== 'POST') { return; } // タイトル $title = filter_input(INPUT_POST, 'title'); if ('' === $title) { throw new Exception('タイトルは入力必須です。'); } // アップロードファイル $test = $_FILES['test']; /** * @see http://php.net/manual/ja/features.file-upload.post-method.php */ if ($test['error'] > 0) { throw new Exception('ファイルアップロードに失敗しました。'); } $tmp_name = $test['tmp_name']; // ファイルタイプチェック $finfo = finfo_open(FILEINFO_MIME_TYPE); $mimetype = finfo_file($finfo, $tmp_name); // 許可するMIMETYPE $allowed_types = [ 'jpg' => 'image/jpeg' , 'png' => 'image/png' , 'gif' => 'image/gif' ]; if (!in_array($mimetype, $allowed_types)) { throw new Exception('許可されていないファイルタイプです。'); } // ファイル名(ハッシュ値でファイル名を決定するため、同一ファイルは同盟で上書きされる) $filename = sha1_file($tmp_name); // 拡張子 $ext = array_search($mimetype, $allowed_types); // 保存作ファイルパス $destination = sprintf('%s/%s.%s' , 'test' , $filename , $ext ); // アップロードディレクトリに移動 if (!move_uploaded_file($tmp_name, $destination)) { //on line 66 throw new Exception('ファイルの保存に失敗しました。'); } // Exif 情報の削除 $imagick = new Imagick($destination); $imagick->stripimage(); $imagick->writeimage($destination); // データベースに登録 $sql = 'INSERT INTO `images` (`id`, `title`, `path`) VALUES (NULL, :title, :path) '; $arr = []; $arr[':title'] = $title; $arr[':path'] = $destination; $lastInsertId = insert($sql, $arr); // 成功時にページを移動する header(sprintf('Location: image.php?id=%d', $lastInsertId)); } try { // ファイルアップロード file_upload(); } catch (Exception $e) { $error = $e->getMessage(); } ?> <!DOCTYPE HTML> <html lang="ja"> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .error { color: red; } </style> </head> <body> <div id="wrap"> <?php if (isset($error)) : ?> <p class="error"><?= h($error); ?></p> <?php endif; ?> <form action="" method="post" enctype="multipart/form-data"> <p> <label for="title">タイトル</label> <input type="text" name="title" id="title" /> </p> <p> <label for="test">画像ファイル</label> <input type="file" name="test" id="test" /> </p> <p> <button type="submit">送信</button> </p> </form> </div> </body> </html>

image.php

<?php /** * image.php */ require 'common.php'; try { $id = filter_input(INPUT_GET, 'id'); // データベースからレコードを取得 $sql = 'SELECT `id`, `title`, `path` FROM `images` WHERE `id` = :id'; $arr = []; $arr[':id'] = $id; $rows = select($sql, $arr); $row = reset($rows); } catch (Exception $e) { $error = $e->getMessage(); } ?> <!DOCTYPE HTML> <html lang="ja"> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .error { color: red; } </style> </head> <body> <div id="wrap"> <?php if (isset($error)) : ?> <p class="error"><?= h($error); ?></p> <?php endif; ?> <p><?= h($row['title']); ?></p> <p> <img src="<?= h($row['path']); ?>" alt="<?= h($row['title']); ?>" /> </p> </div> </body> </html>

###testのパーミッション

drwxrwxrwx 5 neko admin 160 1 6 19:26 test

###作成したテーブル

CREATE TABLE `images` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `title` varchar(32) DEFAULT NULL, `path` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

###ディレクトリ構造

test ┣ common.php ┣ image.php ┗ index.php

試したこと

testのパーミッションが755だったので一応777にしてみました。

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

エラーのon line 66の部分はindex.phpに記載しておきました。
参考にしたサイト

OS:mac
mysql:5.6
php:7.1

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

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

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

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

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

guest

回答2

0

sha1_file() ←これ、なんのために入れてますか?

もし「DBに保存するためのファイル名」としているのでしたら、move_uploaded_fileの第1引数に入れる情報に使うのは間違っています。
第1引数はファイルの実体があるパスです。
sha1_file()をかけることによりそのパスがハッシュ化されます。
実体を持っているのは、今回ですと$_FILES['test']['tmp_name']です。
そのtmp_nameを加工したパスにファイルがないのは明らかです。
コード内のどこにもファイルのリネームをしている場所は見受けられませんしね。

ただ、そもそもis_uploaded_file() / move_uploaded_file() の必要性?を問う記事もありますので、ファイルアップロードの例外処理はこれぐらいしないと気が済まないと併せて読んでみてください。


前の質問の回答のコメントで大事なこと書いてるんですけど、スルーされたまま突き進んでいるみたいなのでこちらに再掲します。


ネットから拾い集めたコードはバグだらけと思ってください。
**自身で理解できないのに使っていると結局身につきません。(デバッグ依頼のような内容になっています) **
※正しく活用できず結局バグコードになるという意

投稿2020/01/06 12:42

編集2020/01/07 10:38
m.ts10806

総合スコア80875

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

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

Ms.yy

2020/01/06 21:34

sha1_file()に関してもよくわかりません、とりあえず動いてから理解しようとしていました。 ということは、参考にしたサイトの方もバグになっていることに気づかずqiitaに投稿しているということでしょうか?
m.ts10806

2020/01/06 21:39

言い換えると 「理解せずに使うとどんな評価の高い記事のコードもバグコードにしかならない」 ご自身の行為のことです。 何を参考にしたのかは存じ上げませんが、理解せずに使ってることでバグコードにしてしまっています。 これまでの質問からすると自明かと思いますけど。 プログラムは書いた通りにしか動かないので理解せずに使うというのはあり得ません。
Ms.yy

2020/01/06 23:38

なるほどです。 ちなみにこの画像アップロードのコードを理解するには何が必要でしょうか? sha1_file()やmove_uploaded_fileの意味を理解すれば自然と分かるものですか
m.ts10806

2020/01/07 00:04

回答を一通り読んでもらったらと。(読まれた感のないコメントばかりで大変残念に感じています) 全部書いてますし参考記事も記載しています。PHPマニュアルのリンクもあります。 基本的に初心者が遭遇する問題は下記三点きちんと回せば解決します。 ・エラーの意味を理解する ・デバッグをする ・PHPマニュアルで仕様を確認する 3番目を抜かす人が非常に多いため解決できないわけです。 (特に全部抜かしてた場合、丸投げデバッグ依頼と認識されるのは当然ですよね)
Ms.yy

2020/01/07 03:21 編集

申し訳ございません、URL先は確認させて頂いております。 おっしゃるとおりマニュアルはほとんど見ていません・・・ どうしてもとっつきにくく、webで他のわかりやすい方の記事を参考にしてしまいます。
m.ts10806

2020/01/07 03:48

たぶんどの質問者にも私は言ってきてるので、Ms.yyさんにも言ってる気がします。 公式またはそれに準じたドキュメントを活用できるようにならないとずっと成長しません。 どこかで拾ったコードが正しいとどうやって担保できますか?を突き詰めてください。 コピペして動く動かないを繰り返してるだけなので身に付きっこないです。
m.ts10806

2020/01/07 03:50

「動けば正しい、動かなければ正しくない」ではなく、「動くように理解してきちんと組み込む」が正しいです。そのためにはドキュメントは必携です。
Ms.yy

2020/01/07 08:37

了解しました。 マニュアル挑戦してみます。
m.ts10806

2020/01/07 10:42

https://qiita.com/suin/items/79a6851f83ac5dfdca94 この方の記事、前後の記事もあわせて読むと理解が深まると思います。 PHPマニュアルは「辞書」としての活用が最も多いので本来は「挑戦する」ものではないですよ。 「機能の意味を調べる」くらいでどんどん使ったら良いです。 特に仕様理解してない機能が沢山あるようなので。PHPマニュアル活用すれば読めるようになって「何がおかしいか」に気づけるようになります。 結局下記3点「やるか」どうかです。 ・エラーの意味を理解する ・デバッグをする ・PHPマニュアルで仕様を確認する
Ms.yy

2020/01/07 13:46

url先拝見いたしました。 m.ts10806さんと同じでマニュアルを推していますね 必要な時だけ、該当項目を探して使うという形ですね。 こちらの3点意識してみます????
guest

0

自己解決

今回の2点のエラーに関しては下記部分のtestを../testに変更したら今回のエラーは解消されました。

実態のあるフォルダへ導けていなかったのが問題でした。

$destination = sprintf('%s/%s.%s' , '../test' //実態のあるフォルダへのパスを記載 , $filename , $ext );

投稿2020/01/09 12:59

Ms.yy

総合スコア83

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問