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

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

ただいまの
回答率

90.76%

  • JavaScript

    15298questions

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

  • HTML

    8312questions

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

  • Python

    6862questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Ajax

    1034questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

  • Django

    907questions

    DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 527

yutaro0822

score 1

 前提・実現したいこと

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ベストアンサー

+4

AJAX部分で

Ext.Ajax.request

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

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/31 22:20

    ajaxで失敗していました。

    そこで
    <script>
    var canvas = document.getElementById('can');
    //base64データを取得(エンコード)
    var base64 = canvas.toDataURL('image/png');

    var fData = new FormData();
    fData.append('img', base64);

    $(function() {
    $('#button').click(
    function() {
    $.ajax({
    type: 'POST',
    data: fData ,
    contentType: false,
    processData: false,
    success: function(data) {
    $('#text').html(data);
    },
    error: function(data) {
    alert('error');
    }
    });
    }
    );
    });
    </script>

    こちらのように考えたのですが、ERR_connection_refused
    になってしまいます。コード等に問題ありますでしょうか??

    キャンセル

  • 2018/05/31 22:28

    dataType: 'json' 指定してみたらどうでしょう?

    キャンセル

  • 2018/05/31 22:38

    補足です。

    html
    <canvas id="can" width="400px" height="300px"></canvas>
    <input type="button" id="button" value="button"/>

    js部分
    <script>
    var canvas = document.getElementById('can');
    //base64データを取得(エンコード)
    var base64 = canvas.toDataURL('image/png');

    var fData = new FormData();
    fData.append('img', base64);

    $(function() {
    $('#button').click(
    function() {
    $.ajax({
    type: 'POST',
    data: fData ,
    contentType: false,
    processData: false,
    dataType: 'json',
    success: function(data) {
    console.log('success');
    },
    error: function(data) {
    alert('error');
    }
    });
    }
    );
    });
    </script>

    これでも出来ないのですが、どうしてでしょうか?
    なんども恐縮です

    キャンセル

  • 2018/05/31 22:47

    送信側は問題ないように思うのですが、ボタン押した際にデベロッパーツールの Network タブに表示される通信の内容はどうなっていますか?
    Response Headers のステータスなどが知りたいです。

    キャンセル

  • 2018/05/31 23:23

    (index):16 Uncaught TypeError: Cannot read property 'toDataURL' of null

    とありますね。png化が出来なさそうですね。

    キャンセル

  • 2018/05/31 23:30

    あー、canvas 要素の取得に失敗してますね。こうしましょう。

    $(function() {
    var canvas = document.getElementById('can');
    //base64データを取得(エンコード)
    var base64 = canvas.toDataURL('image/png');

    var fData = new FormData();
    fData.append('img', base64);

    $('#button').click(
    function() {
    $.ajax({
    type: 'POST',
    data: fData ,
    contentType: false,
    processData: false,
    dataType: 'json',
    success: function(data) {
    console.log('success');
    },
    error: function(data) {
    alert('error');
    }
    });
    }
    );
    });

    キャンセル

  • 2018/05/31 23:34

    Failed to load resource: the server responded with a status of 403 (Forbidden)

    となってしまいます。。。

    キャンセル

  • 2018/05/31 23:40

    csrf_tokenとかの問題なんでしょうか??

    キャンセル

  • 2018/05/31 23:51

    それっぽいですね。

    HTML の <form> の中に {% csrf_token %} 記載して、

    JavaScript を↓のような感じで、クリックしたタイミングで <form> タグの内容から FormData を生成するようにしましょう。こうすれば FormData に CSRF トークンが入ります。

    $('#button').click(
    function() {
    var fData = new FormData(document.getElementByID('form-id'));
    fData.append('img', 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.76%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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

  • JavaScript

    15298questions

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

  • HTML

    8312questions

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

  • Python

    6862questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Ajax

    1034questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

  • Django

    907questions

    DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。