HTMLのフォームにファイルアップロード機能がありますが、canvasで描いたものをform
の他の要素と一緒にPOSTで送信することはできないでしょうか。
調べてみると、「他の要素とは別にAjaxで送信する」「Data URIやBase64に変換してアップロードする」というような手法はあったのですが、できることならサーバ側に手を入れず、通常の<input type="file" />
を受け取るのと同様に処理できればいいなと考えています。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/06/24 01:23
回答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総合スコア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総合スコア1698
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
var base64= this.canvas.toDataURL('image/png');
投稿2015/06/24 01:09
総合スコア775
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/06/24 01:15
2015/06/24 01:23
2015/06/24 01:25
2015/06/24 02:17
2015/06/24 02:48
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。