発生している問題・エラーメッセージ
JavascriptのgetUserMediaを用いてwebカメラを実装し、撮影した画像をcanvasに表示し、その画像をLaravelのStorageを使ってlocalに保存するようなプログラムを作成しています。
一応、localへの保存まで動くのですが、保存した画像をMacで開こうとすると
「ファイル"sample.png"を開ませんでした。ファイルが壊れているか、"プレビュー"が認識しないフォーマットを使用している可能性があります。」
というメッセージが出て、開くことができません。
原因がわからず、そもそも本当に画像が壊れているのかすら分かりません。
前提
OS: macOS Catalina 10.15.4
Laravel: 7.12.0
webサーバ: nginx
Laradockで構築しています。
javascriptのコードは root/resources/js/ に作成し、npm run watchコマンドで変換しています。
最終的には、このプログラムで撮影した画像をAWS S3に保存し、別のプログラムでローカルにダウンロードしたいと考えています。
該当のソースコード
// web.php <?php use Illuminate\Support\Facades\Route; Route::get('/', 'TestController@index'); Route::post('/', 'TestController@store');
// capture_image.blade.php <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="{{ asset('css/style.css') }}"> <title>カメラ サンプル</title> <meta name="description" content=""> <meta name="keywords" content=""> <meta name="csrf-token" content="{{ csrf_token() }}"> </head> <body> <h2>Video</h2> <video id="video_area" width="640" height="480" style="background-color: #000" autoplay></video> <button id="start">映像表示開始</button> <button id="capture">撮影</button> <form id="image_form" action="{{ url('/') }}" method="post"> @csrf <input id="image" type="hidden" name="image" value=""> <input id="submit_image" type="submit" name="submit" value="送信"> </form> <canvas id="captured_image"></canvas> <script src="{{ asset('js/script.js') }}"></script> </body> </html>
// script.js npm run watchで変換する前です 'use strict'; var video_area = document.getElementById('video_area'); var start = document.getElementById('start'); var capture = document.getElementById('capture'); // 「映像表示開始」を押下で、getUserMedia を使って映像をに表示 start.addEventListener('click', () => { navigator.mediaDevices.getUserMedia({ video: true, audio: false }) .then(stream => video_area.srcObject = stream) .catch(err => alert(`${err.name} ${err.message}`)); }, false); // 「撮影」を押下で、canvasに撮影した画像を表示し、formの<input type=hidden>にダウンロードURLを埋め込み capture.addEventListener('click', () => { var ci = document.getElementById('captured_image'); var ci_context = ci.getContext('2d'); var va = document.getElementById('video_area'); ci.width = va.videoWidth; ci.height = va.videoHeight; ci_context.drawImage(va, 0, 0); document.getElementById('image').value = ci.toDataURL('image/png'); }, false);
// TestController.php <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; class TestController extends Controller { public function index() { return view('capture_image'); } public function store(Request $request) { $canvas = $request->input('image'); if (isset($canvas)) { $canvas = preg_replace('<data:image/png;base64,>', '', $canvas); $canvas = base64_decode($canvas); $result_image = imagecreatefromstring($canvas); Storage::disk('public')->put('sample.png', imagepng($result_image)); } return redirect('/'); } }
再現手順
- 「映像表示開始」をクリック
- 「撮影」をクリック
- 「送信」をクリック。root/storage/app/public/sample.png が作成される。
- Macで該当ファイルを表示(プレビュー.appをデフォルトで使用)すると、上述したエラーで開くことができない。
試したこと
①該当ファイルをchromeで開いてみても、表示されない(以下の添付画像参照)。
②script.jsに以下のコードを追加し実行すると、画像をローカルにダウンロードできる。
capture.addEventListener('click', () => { var ci = document.getElementById('captured_image'); var ci_context = ci.getContext('2d'); var va = document.getElementById('video_area'); ci.width = va.videoWidth; ci.height = va.videoHeight; ci_context.drawImage(va, 0, 0); document.getElementById('image').value = ci.toDataURL('image/png'); var link = document.createElement('a'); //追加 link.href = ci.toDataURL('image/png'); //追加 link.download = 'sample.png'; //追加 link.click(); //追加 }, false);
③TestController.phpを以下のように修正すると、ブラウザ上に画像を表示できる。
public function store(Request $request) { $canvas = $request->input('image'); if (isset($canvas)) { $canvas = preg_replace('<data:image/png;base64,>', '', $canvas); $canvas = base64_decode($canvas); $result_image = imagecreatefromstring($canvas); // 以下の一文をコメントアウト //Storage::disk('public')->put('sample.png', imagepng($result_image)); header('Content-Type: image/png'); //追加 imagepng($result_image); //追加 imagedestroy($result_image); //追加 } return redirect('/'); }
ということは、つまり、Storageの一文がうまく機能していないということでしょうか?
ご教授のほど、よろしくお願い致します。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/05 02:58
2020/06/05 04:04