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

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

新規登録して質問してみよう
ただいま回答率
85.37%
canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

Q&A

3回答

26320閲覧

Canvasの中身を、formとしてPOSTしたい

maisumakun

総合スコア145930

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

0グッド

0クリップ

投稿2015/06/24 01:06

HTMLのフォームにファイルアップロード機能がありますが、canvasで描いたものをformの他の要素と一緒にPOSTで送信することはできないでしょうか。

調べてみると、「他の要素とは別にAjaxで送信する」「Data URIやBase64に変換してアップロードする」というような手法はあったのですが、できることならサーバ側に手を入れず、通常の<input type="file" />を受け取るのと同様に処理できればいいなと考えています。

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

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

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

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

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

orange0190

2015/06/24 01:19

input type="file"のみですか?hiddenではダメということでしょうか。
maisumakun

2015/06/24 01:23

どんな要素でも、サーバ側でmultipart/form-dataとして受け取れれば大丈夫です。
guest

回答3

0

手抜き実装ですが、こんな感じでしょうか。

multipart/form-dataのファイルとして受け取りたいなら、canvasの画像をBlobオブジェクトに変換し、FormDataオブジェクトに追加したうえでAjax送信すれば実現できます。
また、FormDataオブジェクトをフォームの要素を指定して生成すれば、「他のform要素と一緒に」送信できます。

ただし、BlobオブジェクトやFormDataオブジェクトに対応しているのは比較的新しいブラウザだけです。
具体的には…

  • Internet Explorer 10 以上
  • Google Chrome 20 以上
  • Safari 6 以上
  • Firefox 13 以上
  • Opera 12.1 以上

以上のブラウザが対応しています。
そして、これより前のブラウザなどでは対応していません。

対応していないブラウザでは、他の回答にあるようにData URIやBase64に変換してアップロードするしか方法は無いと思います。

HTML

1<canvas id="canvas-id" width="100" height="100"></canvas> 2 3<form action="/upload" method="post" id="form-id"> 4 <input type="submit"> 5</form>

JavaScript

1/** 2 * HTMLCanvasElement.toBlobの互換関数。 3 * toBlobメソッドとほぼ同等の動作を行う。 4 * 対応していない場合、コールバック関数の引数にはnullが返される。 5 * 6 * @param {Node} canvas canvas要素のDOMノード 7 * @param {function((Blob|null))} callback コールバック関数。第一引数に、生成したBlobオブジェクト、またはnullが渡される 8 * @param {string=} type 画像形式の文字列 9 * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill 10 */ 11function canvasToBlob(canvas, callback, type) { 12 if (!type) { 13 type = 'image/png'; 14 } 15 16 if (canvas.toBlob) { 17 canvas.toBlob(callback, type); 18 } else if (canvas.toDataURL && window.Uint8Array && window.Blob && window.atob) { 19 var binStr = atob(canvas.toDataURL(type).replace(/^[^,]*,/, '')), 20 len = binStr.length, 21 arr = new Uint8Array(len); 22 23 for (var i = 0; i < len; i++) { 24 arr[i] = binStr.charCodeAt(i); 25 } 26 27 callback(new Blob([arr], { type: type })); 28 } else { 29 callback(null); 30 } 31} 32 33/** 34 * canvas画像の送信処理 35 * 36 * @param {Element} formElem フォームのDOMノード 37 */ 38function send(formElem) { 39 var canvasElem = document.getElementById('canvas-id'); 40 41 if (window.FormData) { 42 /** 43 * FormDataオブジェクトに対応している場合、 44 * canvas要素の画像をBlobオブジェクトに変換し、 45 * ファイルとして送信することを試みる 46 */ 47 canvasToBlob(canvasElem, function (canvasBlob) { 48 if (canvasBlob) { 49 /** 50 * canvas要素の画像をBlobオブジェクトとして出力できた場合、 51 * FormDataオブジェクトにファイルとして追加し、送信 52 */ 53 54 /** 55 * FormDataオブジェクトを生成 56 */ 57 var fd = new FormData(formElem); 58 /** 59 * Blobオブジェクトを追加。 60 * これにより、サーバ側ではcanvas-imageパラメータから 61 * 画像ファイルとして取り込める 62 */ 63 fd.append('canvas-image', canvasBlob); 64 65 /** 66 * XMLHttpRequestオブジェクトを生成 67 */ 68 var xhr = new XMLHttpRequest(); 69 70 // ------------------------- 71 // Ajax通信完了時の処理などを記述… 72 // ------------------------- 73 74 /** 75 * Ajax通信の送信先・送信形式を指定 76 * この例では、送信先としてフォームのaction属性値を使用 77 */ 78 xhr.open('POST', formElem.action, true); 79 80 /** 81 * FormDataオブジェクトをAjax送信 82 */ 83 xhr.send(fd); 84 } else { 85 /** 86 * canvas要素の画像をBlobオブジェクトとして出力できなかった場合、 87 * 送信できなかった事をアラート 88 */ 89 alert('canvasの内容を送信できませんでした。\nお使いのブラウザは、Blobオブジェクトの生成に必要な機能に対応していません。'); 90 } 91 }, 'image/png'); 92 } else { 93 /** 94 * FormDataオブジェクトに対応していない場合、 95 * 送信できない事をアラート 96 */ 97 alert('canvasの内容を送信できませんでした。\nお使いのブラウザは、FormDataオブジェクトに対応していません。'); 98 } 99} 100 101/** 102 * フォームが送信される時に実行する処理 103 */ 104document.getElementById('form-id').addEventListener('submit', function (e) { 105 /** 106 * フォームの要素を取得 107 */ 108 var formElem = this; 109 110 /** 111 * フォームの送信をキャンセル 112 */ 113 e.preventDefault(); 114 115 /** 116 * フォームをAjax送信 117 */ 118 send(formElem); 119}, false);

投稿2015/10/26 11:04

編集2015/10/26 18:20
sounisi5011

総合スコア697

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

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

0

lang

1<canvas id="canvas"></canvas> 2<form id="form"> 3<inupt type="text"/> 4<input type="submit" id="submit_btn"> 5</form>

上記のようなものだと仮定してお答えします。
以下のようにしてみてはいかがでしょうか。

lang

1var canvas = document.getElementById("canvas"); 2document.getElementById("submit_btn").addEventListener( 3 "submit", submitForm, false 4); 5 6function submitForm(event){ 7 event.preventDefaulst(); 8 var form = document.getElementById("form"); 9 var base64 = canvas.toDataURL(); 10 var newInput = document.createElement("input"); //input要素作成 11 newInput.type="hidden"; 12 newInupt.name = "canvas"; 13 newInput.value=base64; //値を設定 14 form.appendChild(newInput); //formにinupt要素を追加 15 16 form.submit(); //送信 17}

動作未検証ですので、参考程度にしてください。

投稿2015/06/24 01:38

編集2015/06/24 02:00
orange0190

総合スコア1698

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

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

0

var base64= this.canvas.toDataURL('image/png');

参考
http://qiita.com/0829/items/a8c98c8f53b2e821ac94

投稿2015/06/24 01:09

nanndemoiikara

総合スコア775

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

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

maisumakun

2015/06/24 01:15

えっと、「他のform要素と一緒に」行う方法ではなさそうなのですが……
nanndemoiikara

2015/06/24 01:23

すみませんでした。。。 質問の意図を正しく理解しておりませんでした。 無視して下さい。
nanndemoiikara

2015/06/24 01:25

こちらinput[type="hidden"]にbase64の文字列をpostして処理してはだめでしょうか?
sounisi5011

2015/06/24 02:17

参考ページの「Blob版」にて、FormDataオブジェクトによる送信を行っています。 FormDataオブジェクトを生成する際、第一引数にform要素を指定することで、フォーム内の入力コントロールの値がFormDataオブジェクトに設定されます。 http://hakuhin.jp/js/form_data.html 以降は、参考ページに書いてあるとおり実装すればOKです。 参考ページの例では、<input type="file" name="image">にファイルを選択して送信した時と同じデータをサーバ側で扱うことが出来ます。 なお、FormDataオブジェクトはAjaxで送信するものなので、form要素にsubmitイベントを設定し、フォームの送信をキャンセルする必要があります。 また、FormDataオブジェクトに対応していないブラウザではこの方法は利用できません。
nanndemoiikara

2015/06/24 02:48

sounisi5011様 回答頂きありがとうございます。 勉強になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問