質問するログイン新規登録

Q&A

解決済

2回答

4828閲覧

Webカメラで撮影した画像をサーバー上の指定のディレクトリに保存する

g45.07

総合スコア13

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

0クリップ

投稿2021/09/08 02:02

編集2021/09/08 02:46

0

0

前提・実現したいこと

●前提
・webアプリケーションを作っています

●実現したいこと
①ブラウザ上でwebカメラを起動
②撮影ボタンを押すとwebカメラの画像がcanvasに格納
③アップロードボタンを押すと、サーバー上の指定のディレクトリに画像ファイルを保存

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

①、②はできましたが、③のやり方が分かりません。

試したこと

・javascriptでcanvasを画像ファイルに変換(toDataURLを使った)
これ以降どのように保存をしていいか色々調べてもピンときません。
画像ファイルに本当に変換できているのかもわかりません。

###現在のコード

HTML

1<div class="picturePreview"> 2 <div id="videoPreview"></div> 3 <div id="canvasPreview"></div> 4 <form> 5 <button type="button" id="shutter" class="video-preview-btn" onclick="Snap();">撮影</button> 6 </form> 7 <form> 8 <button type="button" id="save-picture" class="video-preview-btn" onclick="Save();">保存</button> 9 </form> 10 </div>

javascript

1 2 const cameraSize = { w: 600, h: 400 }; 3 const resolution = { w: 1080, h: 720 }; 4 let video; 5 let media; 6 7 // video要素をつくる 8 video = document.createElement('video'); 9 video.id = 'video'; 10 video.width = cameraSize.w; 11 video.height = cameraSize.h; 12 video.autoplay = true; 13 document.getElementById('videoPreview').appendChild(video); 14 15 // video要素にWebカメラの映像を表示させる 16 media = navigator.mediaDevices.getUserMedia({ 17 audio: false, 18 video: { 19 width: { ideal: resolution.w }, 20 height: { ideal: resolution.h } 21 } 22 }).then(function(stream) { 23 video.srcObject = stream; 24 }).catch(function (error) { 25 console.error('mediaDevice.getUserMedia() error:', error); 26 return; 27 }); 28} 29 30function Snap(){ 31 32 const canvasSize = { w: 600, h: 400 }; 33 let canvas; 34 let canvasCtx; 35 var retake; 36 37 // canvas要素をつくる 38 canvas = document.createElement('canvas'); 39 canvas.id = 'canvas'; 40 canvas.width = canvasSize.w; 41 canvas.height = canvasSize.h; 42 document.getElementById('canvasPreview').appendChild(canvas); 43 44 // コンテキストを取得する 45 canvasCtx = canvas.getContext('2d'); 46 47 canvasCtx.drawImage(video, 0, 0, canvas.width, canvas.height); 48 49 const tracks = document.getElementById('video').srcObject.getTracks(); 50 tracks.forEach(track => { 51 track.stop(); 52 }); 53 54} 55 56function Save(){ 57 58 const picture = canvas.toDataURL("image/png"); 59 60 //色々調べてここで止まっています。 61

①pictureをサーバー側に送信する方法が分かりません。

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

フロント:HTML,CSS,JavaScript,jQuery
サーバー:C#
DB:SQL Server

説明不足な部分が多々あるかと思いますが、そういった部分も含めてご指摘いただけると嬉しいです。
宜しくお願いします。

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

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

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

guest

回答2件

0

ベストアンサー

C#、ASP.NETでの正当な方法はSurferOnWwwさんが回答してくださっているので、HTTPの仕組みを理解していれば特に難しいことではないということを示す、別の方法で実証してみた回答です。

ここではHTMLでカメラで撮影した画像云々はあまり関係無く、Canvas上の画像をサーバーに送ってそのデータをどう処理してファイルとしてサーバー上に保存するのか、ということが主題だと思うので、必要な部分のみ示します。ご提示のコードをもとにカメラで撮影した画像をCanvas上に表示し、送信することはできていたのですが、撮影のタイミングが一致しないなど少なくともこちらで試す限りでは不具合がありましたので、割愛させてもらいます。

まず、HTMLのCanvas上に画像を表示し、下記コード中のdoSubmit()関数でCanvasのtoDataURLで得たデータをPOSTメソッドで送信するコードです。

先頭行には識別用のデータがあるので、それを除去したかたちでBASE64でエンコードされた画像データ部をXMLHttpRequestを使い、サーバーにHTTPリクエストで送信します。

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="utf-8" /> 5 <title>test1</title> 6</head> 7<body> 8 <div> 9 <canvas id="canvas1" width="160" height="160" /> 10 </div> 11 <div> 12 <form> 13 <button type="button" id="button1" onclick="doSubmit();">Submit!</button> 14 </form> 15 </div> 16 17 <script> 18 19 window.onload = () => { 20 const canvas = document.getElementById("canvas1"); 21 const ctx = canvas.getContext("2d"); 22 23 // 画像読み込み 24 const image = new Image(); 25 image.src = "./Lenna.jpg"; 26 image.onload = () => { 27 ctx.drawImage(image, 0, 0); 28 }; 29 }; 30 31function doSubmit(){ 32 33 const picture = canvas1.toDataURL("image/png"); 34 35 console.log('length:' + picture.length); 36 37 // 先頭の "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA"...な文字列中から必要なデータを抽出 38 let seplAt = picture.indexOf(","); 39 // 先頭のメタ情報を取得 40 let meta = picture.substring(0, seplAt); 41 console.log("meta=" + meta); 42 43 let contentType = meta.substring(meta.indexOf(":") + 1); 44 console.log("contentType=" + contentType); 45 46 // コンテントボディ部相当を取得 47 let contentBody = picture.substring(seplAt + 1, picture.length); 48 console.log("contentBody.length=" + contentBody.length); 49 50 var xhr = new XMLHttpRequest(); 51 xhr.onreadystatechange = function () { 52 if (this.readyState != 4) { 53 console.log('readyState=' + this.readyState); 54 return; 55 } 56 57 if (this.status == 200) { 58 // HTTPサーバーからHTTPステータス200(OK)が返った 59 alert('HTTP status: OK'); 60 } 61 } 62 63 xhr.open("POST", 'http://localhost:8000/cgi-bin/t1.cgi', true); 64 xhr.setRequestHeader('Content-Type', 'text/plain'); 65//NG xhr.setRequestHeader('Content-Transfer-Encoding', 'base64'); 66 67 // コンテントボディ部を送信 68 xhr.send(contentBody); 69} 70 </script> 71</body> 72</html>

http://localhost:8000/cgi-bin/t1.cgi で実行されるサーバー側のプログラムが以下のPython3スクリプトです。
CGIと言う現役ではあるもののWEBアプリとしては古代技術wの部類です。簡単であることを示すため、Python3のcgiモジュールなどは使わずベタに処理します。t1.htmlがあるディレクトリ上に、image.png という名前のPNG画像ファイルを保存します。

Python3

1#!/usr/bin/python3 2# t1.cgi 3 4import sys 5import os 6import base64 7 8# POSTメソッドなので、CONTENT_LENGTH環境変数の値を取得 9content_length = os.environ['CONTENT_LENGTH']; 10 11# POSTのコンテントボディ部を標準入力から取得 12source = sys.stdin.read(content_length) 13 14# バイナリ列にエンコードして参考データとしてファイルに保存しておく。 15data = source.encode() 16with open('./image.txt', 'wb') as f: 17 f.write(data) 18 19# BASE64からデコードして画像ファイルとして保存。 20bindata = base64.b64decode(data) 21with open('./image.png', 'wb') as f: 22 f.write(bindata) 23 24print("Content-Type: text/plain") 25print() 26print("OK")

で、これを実行できるようにします。

terminal

1$ find ./ -type f 2./cgi-bin/t1.cgi 3./Lenna.jpg 4./t1.html 5 6$ python3 -m http.server --cgi 7Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

ブラウザ上で実行している様子です。
イメージ説明

http://localhost:8000/t1.html にアクセスし、Canvas上に画像が表示されていることを確認した上で「Submit!」ボタンを押すと、サーバー側ではimage.pngと言う名前のPNGファイルを保存します。クライアント側からはtoDataURLで得たBASE64エンコードの画像データをPOSTメソッドのコンテントボディ部に収めて送信し、サーバー側ではコンテントボディ部を取り出してBASE64からデコードし、画像ファイルとして保存する、という流れです。

HTTPについておおむね理解すれば、技術要素として何を調べていけば実現できるかということが分かるのだと思います。それをベースに、C#、ASP.NET、PHP、Java、Javaサーブレットなどプログラミング言語やフレームワークを選び、使います。

投稿2021/09/10 02:37

編集2021/09/10 02:59
dodox86

総合スコア9427

dodox86

2021/09/10 02:40

回答本文中に書き洩らしましたが、送信するデータの形式(ここではPOSTメソッドのコンテントボディ部がPNGファイルのBASE64エンコード)をクライアント側、サーバー側で認識合わせをしておく必要があるので、製品レベルではそういったことも意識してインターフェース仕様を決めることが必要です。
g45.07

2021/09/10 04:45

回答ありがとうございます。 解決しました。 HTTPについてしっかり勉強してみたいと思います。
guest

0

③アップロードボタンを押すと、サーバー上の指定のディレクトリに画像ファイルを保存

「①、②はできましたが」ということなのでブラウザ上の canvas に静止画像を表示するところまではできており、canvas に表示された画像データを取得してアップロードしたいということと理解してレスします。

以下の記事が参考になりませんか?

canvas の画像をアップロード
http://surferonwww.info/BlogEngine/post/2015/07/02/upload-image-drawn-on-html5-canvas.aspx

上の記事のサンプルコードの中の uploadImage メソッドを見てください。ボタンクリックでこのメソッドが呼び出されると、canvas の画像データを toDataURL メソッドを使って Data URL 形式の文字列として取得し、jQuery.Ajax を使って JSON 形式で Web サーバーに送信しています。

Web アプリが何だか分からないのですが、JSON 形式で受け取って、その中の Data URL 形式の文字列を元の画像データのバイト配列に変換し、ファイル保存することができるなら何だって OK と思います。

上の記事のサンプルコードの中の ReceiveImage メソッドは、ASP.NET Web Forms アプリで Web サービスのメソッドを使って受け取って保存する例です。

投稿2021/09/08 05:02

退会済みユーザー

退会済みユーザー

総合スコア0

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.25%

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

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

質問する

関連した質問