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

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

ただいまの
回答率

90.40%

  • canvas

    285questions

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

  • POST

    247questions

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

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

受付中

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 8,695

maisumakun

ユーザーランキング総合1位

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • orange0190

    2015/06/24 10:19

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

    キャンセル

  • maisumakun

    2015/06/24 10:23

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

    キャンセル

回答 3

+1

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

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に変換してアップロードするしか方法は無いと思います。

<canvas id="canvas-id" width="100" height="100"></canvas>

<form action="/upload" method="post" id="form-id">
  <input type="submit">
</form>

/**
 * HTMLCanvasElement.toBlobの互換関数。
 * toBlobメソッドとほぼ同等の動作を行う。
 * 対応していない場合、コールバック関数の引数にはnullが返される。
 *
 * @param {Node} canvas canvas要素のDOMノード
 * @param {function((Blob|null))} callback コールバック関数。第一引数に、生成したBlobオブジェクト、またはnullが渡される
 * @param {string=} type 画像形式の文字列
 * @link https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill
 */
function canvasToBlob(canvas, callback, type) {
    if (!type) {
        type = 'image/png';
    }

    if (canvas.toBlob) {
        canvas.toBlob(callback, type);
    } else if (canvas.toDataURL && window.Uint8Array && window.Blob && window.atob) {
        var binStr = atob(canvas.toDataURL(type).replace(/^[^,]*,/, '')),
        len = binStr.length,
        arr = new Uint8Array(len);

        for (var i = 0; i < len; i++) {
            arr[i] = binStr.charCodeAt(i);
        }

        callback(new Blob([arr], { type: type }));
    } else {
        callback(null);
    }
}

/**
 * canvas画像の送信処理
 *
 * @param {Element} formElem フォームのDOMノード
 */
function send(formElem) {
    var canvasElem = document.getElementById('canvas-id');

    if (window.FormData) {
        /**
         * FormDataオブジェクトに対応している場合、
         * canvas要素の画像をBlobオブジェクトに変換し、
         * ファイルとして送信することを試みる
         */
        canvasToBlob(canvasElem, function (canvasBlob) {
            if (canvasBlob) {
                /**
                 * canvas要素の画像をBlobオブジェクトとして出力できた場合、
                 * FormDataオブジェクトにファイルとして追加し、送信
                 */

                /**
                 * FormDataオブジェクトを生成
                 */
                var fd = new FormData(formElem);
                /**
                 * Blobオブジェクトを追加。
                 * これにより、サーバ側ではcanvas-imageパラメータから
                 * 画像ファイルとして取り込める
                 */
                fd.append('canvas-image', canvasBlob);

                /**
                 * XMLHttpRequestオブジェクトを生成
                 */
                var xhr = new XMLHttpRequest();

                // -------------------------
                // Ajax通信完了時の処理などを記述…
                // -------------------------

                /**
                 * Ajax通信の送信先・送信形式を指定
                 * この例では、送信先としてフォームのaction属性値を使用
                 */
                xhr.open('POST', formElem.action, true);

                /**
                 * FormDataオブジェクトをAjax送信
                 */
                xhr.send(fd);
            } else {
                /**
                 * canvas要素の画像をBlobオブジェクトとして出力できなかった場合、
                 * 送信できなかった事をアラート
                 */
                alert('canvasの内容を送信できませんでした。\nお使いのブラウザは、Blobオブジェクトの生成に必要な機能に対応していません。');
            }
        }, 'image/png');
    } else {
        /**
         * FormDataオブジェクトに対応していない場合、
         * 送信できない事をアラート
         */
        alert('canvasの内容を送信できませんでした。\nお使いのブラウザは、FormDataオブジェクトに対応していません。');
    }
}

/**
 * フォームが送信される時に実行する処理
 */
document.getElementById('form-id').addEventListener('submit', function (e) {
    /**
     * フォームの要素を取得
     */
    var formElem = this;

    /**
     * フォームの送信をキャンセル
     */
    e.preventDefault();

    /**
     * フォームをAjax送信
     */
    send(formElem);
}, false);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/24 10:15

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

    キャンセル

  • 2015/06/24 10:23

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

    キャンセル

  • 2015/06/24 10:25

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

    キャンセル

  • 2015/06/24 11:17

    参考ページの「Blob版」にて、FormDataオブジェクトによる送信を行っています。
    FormDataオブジェクトを生成する際、第一引数にform要素を指定することで、フォーム内の入力コントロールの値がFormDataオブジェクトに設定されます。
    http://hakuhin.jp/js/form_data.html

    以降は、参考ページに書いてあるとおり実装すればOKです。
    参考ページの例では、<input type="file" name="image">にファイルを選択して送信した時と同じデータをサーバ側で扱うことが出来ます。
    なお、FormDataオブジェクトはAjaxで送信するものなので、form要素にsubmitイベントを設定し、フォームの送信をキャンセルする必要があります。
    また、FormDataオブジェクトに対応していないブラウザではこの方法は利用できません。

    キャンセル

  • 2015/06/24 11:48

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

    キャンセル

0

<canvas id="canvas"></canvas>
<form id="form">
<inupt type="text"/>
<input type="submit" id="submit_btn">
</form>
上記のようなものだと仮定してお答えします。
以下のようにしてみてはいかがでしょうか。
var canvas = document.getElementById("canvas");
document.getElementById("submit_btn").addEventListener(
    "submit", submitForm, false
);

function submitForm(event){
    event.preventDefaulst();
    var form = document.getElementById("form");
    var base64 = canvas.toDataURL();
    var newInput = document.createElement("input");  //input要素作成
    newInput.type="hidden";
    newInupt.name = "canvas";
    newInput.value=base64;  //値を設定
    form.appendChild(newInput);  //formにinupt要素を追加

    form.submit(); //送信
}
動作未検証ですので、参考程度にしてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.40%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • canvas

    285questions

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

  • POST

    247questions

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