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

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

ただいまの
回答率

90.23%

canvasを画像化してPOSTで送信したい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 2,164

yutaro0822

score 5

 前提・実現したいこと

Django2.0 での質問です。

htmlに埋め込んだcanvasに描画をしたのち画像化・POSTメソッドで送信しdjangoの方で画像をPILで扱いたいです。

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

0>

OSError: cannot identify image file <_io.BytesIO object at 0x1124636d0>

 該当のソースコード

<div style="border:solid 1px #000000;width:400px">
        <canvas id="can" width="400px" height="300px"></canvas>
        <form action="{% url 'canvas_predict' %}" method="post" id="form-id" enctype="multipart/form-data">
            {% csrf_token %}
        <input type="button" onclick="blob()" id="submit_btn">
        <button type="submit"></button>
        </form>
</div>
var can;
var ct;
var ox=0,oy=0,x=0,y=0;
var mf=false;

function mam_draw_init(){
        //初期設定
        can=document.getElementById("can");
        can.addEventListener("touchstart",onDown,false);
        can.addEventListener("touchmove",onMove,false);
        can.addEventListener("touchend",onUp,false);
        can.addEventListener("mousedown",onMouseDown,false);
        can.addEventListener("mousemove",onMouseMove,false);
        can.addEventListener("mouseup",onMouseUp,false);
        ct=can.getContext("2d");
        ct.strokeStyle="#000000";
        ct.lineWidth=5;
        ct.lineJoin="round";
        ct.lineCap="round";
        clearCan();
        blob();
      }
function onDown(event){
        mf=true;
        ox=event.touches[0].pageX-event.target.getBoundingClientRect().left;
        oy=event.touches[0].pageY-event.target.getBoundingClientRect().top;
        event.stopPropagation();
}
function onMove(event){
       if(mf){
          x=event.touches[0].pageX-event.target.getBoundingClientRect().left;
          y=event.touches[0].pageY-event.target.getBoundingClientRect().top;
          drawLine();
          ox=x;
          oy=y;
          event.preventDefault();
          event.stopPropagation();
       }
}
function onUp(event){
        mf=false;
        event.stopPropagation();
}

function onMouseDown(event){
        ox=event.clientX-event.target.getBoundingClientRect().left;
        oy=event.clientY-event.target.getBoundingClientRect().top ;
        mf=true;
}

function onMouseMove(event){
        if(mf){
          x=event.clientX-event.target.getBoundingClientRect().left;
          y=event.clientY-event.target.getBoundingClientRect().top ;
          drawLine();
          ox=x;
          oy=y;
        }
}

function onMouseUp(event){
        mf=false;
}

function drawLine(){
        ct.beginPath();
        ct.moveTo(ox,oy);
        ct.lineTo(x,y);
        ct.stroke();
}

function clearCan(){
        ct.fillStyle="rgb(255,255,255)";
        ct.fillRect(0,0,can.getBoundingClientRect().width,can.getBoundingClientRect().height);
}



function blob(){
    var base64 = can.toDataURL('image/png');
    var request = {
    url: 'http://localhost:4567/base64',
    method: 'POST',
    params: {
        image: base64.replace(/^.*,/, '')
    },
    success: function (response) {
        console.log(response.responseText);
    }
    };
    Ext.Ajax.request(request);
}
from django.shortcuts import render, redirect
from PIL import Image
import base64
from io import BytesIO

...
def canvas_predict(request):
    code = base64.b64decode(request.POST['csrfmiddlewaretoken'])
    dec_img = Image.open(BytesIO(code))


    return render(request, 'mnist/result.html')

 試したこと

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

は書いてあります

正直、jsのblob()メソッドで本当に送信されたのかも怪しいです。
もしかするとhtml部分で問題があるのではと思っています。

当方初めての質問となり、何かとわからないことだらけです。
かなり調べてもわからなかったので質問させていただきました。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+3

AJAX部分で

Ext.Ajax.request

と書かれていますが、Ext JS をお使いでしょうか?
使っていない場合は jQuery の jQuery.ajax() メソッドを使ってください。

あと、送信できているかどうかは、Google Chorme のデベロッパーツールの Network タブで XHR にフィルタ切り替えすると簡単に通信内容見れますので、そちらで送れてるかどうか見ると良いでしょう。

また、問題なく送れているようなら、サーバー側の問題だと思いますので、その場合は一度 Base64 エンコードされたデータが受信できているかテキストファイルに書き出す等して確認し、ダメだった場合はルーティング等の確認をすると良いと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/01 10:05

    なんども本当に申し訳ないです。

    Pycharmの開発画面のログにはPOST HTTP1. 1 200と表示されて通信に成功してそうですが
    Chrome上でエラーが
    [Violation] 'load' handler took 2006ms
    という風に出てしまいます…

    キャンセル

  • 2018/06/01 15:55

    click イベントの中で重い処理するのがまずいのかもしれません。フォームの submit イベントの中でやってみたらどうでしょうか。

    $('#form-id').on('submit', function(event) {
    event.preventDefault();
    var fData = new FormData(this);
    fData.append('img', base64);
    .
    .
    .
    });

    キャンセル

  • 2018/06/02 18:27

    やはり同じエラーになってしまいます。

    自分のajaxへの理解不足な気がするのでもう一度勉強してきます
    ご丁寧にありがとうございました

    キャンセル

0

<script>
window.addEventListener('DOMContentLoaded', function(e){
  /* canvasの作成 */
  var canvas = document.createElement( "canvas" ) ;
  canvas.width=200;
  canvas.height=200;
  var context = canvas.getContext( "2d" ) ;
  context.beginPath () ;
  context.arc( 100, 100, 50, 0 * Math.PI / 180, 360 * Math.PI / 180, false ) ;
  context.fillStyle = "rgba(255,0,0,0.8)" ;
  context.fill() ;
  context.strokeStyle = "purple" ;
  context.lineWidth = 8 ;
  context.stroke() ;

  /* blobに変換 */
  var type = 'image/png';
  var dataurl = canvas.toDataURL(type);
  var bin = atob(dataurl.split(',')[1]);
  var buffer = new Uint8Array(bin.length);
  for (var i = 0; i < bin.length; i++) {
    buffer[i] = bin.charCodeAt(i);
  }
  var blob = new Blob([buffer.buffer], {type: type});

  /* ajaxで送信 */
  var fd=new FormData();
  fd.append("myfile", blob,"test.png");
  var type = 'image/png';
  var xhr = new window.XMLHttpRequest();
  xhr.open("post","recv.php");
  xhr.responseType = 'blob';
  xhr.send(fd);

  /* 念の為表示*/
  document.querySelector('body').appendChild(canvas);
});

</script>

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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