如何使用Ajax将JavaScript的画布数据发送到Django

时间:2019-04-25 05:58:57

标签: javascript python ajax django

我正在开发一个django应用程序,用户可以在其中触发网络摄像头并捕获照片。这张照片保存在画布中。我想将此图像发送到django视图,通过它可以将图像保存在django服务器中。

我正在使用webrtc触发网络摄像头。我很难用js本身来保存数据,并且在某个地方读到单独使用js无法实现这一点。所以我现在正尝试使用ajax将te数据发送到python,但无法这样做。我是使用canvas和ajax的初学者,因此,详细的说明会有所帮助。

我尝试使用这些答案,但似乎没有一个帮助

Send canvas image data (Uint8ClampedArray) to Flask Server via Ajax

Can't send data back to Django from JS AJAX

到目前为止,这是我的代码

html模板

<center>
    <button type="button" name="button" class='btn btn-outline-dark btn-lg' id='start'>Start Video Capture</button>

    <div class="container-fluid mt-2">
        <video id="video" width="640" height="480" autoplay></video><br>
        <button type="button" data-toggle="modal" data-target="#image_model" class="btn btn-lg btn-dark" id="snap">Snap Photo</button>
    </div>
</center>

<button type="button" class="btn btn-secondary" data-dismiss="modal">Retake</button>
<form action="{% url 'img_submit' %}" method="post" class="image_submit_form">
    {% csrf_token %}
    <input type="submit" value="Use Image" class="btn btn-primary" id="use_image">
</form>

不确定use_image是否需要使用表格将数据发送到python。

javascript代码

// Grab elements, create settings, etc.
var video = document.getElementById('video');
// Elements for taking the snapshot
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

document.getElementById('start').addEventListener("click", function() {
    // Get access to the camera!
    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia({
            video: true
        }).then(function(stream) {
            //video.src = window.URL.createObjectURL(stream);
            video.srcObject = stream;
            video.play();
        });
    }

    $('#snap').fadeIn();

    // Trigger photo take
    document.getElementById("snap").addEventListener("click", function() {
        context.drawImage(video, 0, 0, 640, 480);

        var dataURL = canvas.toDataURL();

        $("#use_image").click(function() {
            let $form = $(".image_submit_form");
            let form_data = new FormData($form[0]);

            $.ajax({
                url: $form.attr('action'),
                type: $form.attr('method'),
                dataType: 'json',
                data: JSON.stringify(dataURL),
                data: {
                    imageBase64: dataURL
                }
            }).done(function() {
                console.log('sent');
            });
        });
    });

});

我很确定自己搞砸了ajax部分。

我仍然没有编写任何代码来用python保存图像,但是我想如果我能以某种方式将canvas数据转换为jpeg或png然后发送给python,这将很容易。我也不明白为什么我们必须将画布数据转换为base64。难道我们只是将其转换为png吗?

请帮助我。 谢谢

[EDIT1]

python views.py

def img_submit(request):
    url = request.POST.dict()
    return HttpResponse(url)

2 个答案:

答案 0 :(得分:0)

也许您的代码工作正常,但这很关键:

 ...


            data: JSON.stringify(dataURL),
            data: {
                imageBase64: dataURL
            }

您不能使用两个相同的键访问来创建对象。 甚至不需要注入两次相同的数据。

删除JSON.stringify行,然后重试!我已经使用websocket完成了此操作,但看不到无法正常工作的原因!

  

data:image / png; base64,iVBORw0K ...

也可以尝试:

.toDataURL("image/png")

检查连接是否正常工作。

发布完整的错误日志!如果您想在没有用户请求(单击)的情况下进行可编程性设置,则可能会遇到权限错误。

我支持它!

var dataURL = "I Need to be global";

document.getElementById("snap").addEventListener("click", function(){

            // WORK ON CLICK    
            ...
           dataURL = canvas.toDataURL();


            // ATTACHING EVENT - NO CALL 
            $("#use_image").click(function() {
               // This will work only on click again on use_image
            })

答案 1 :(得分:0)

我正在使用ajax将rgba像素数组发送到django视图。
就您而言,该代码将是:

        var data_pixel = canvas.getContext('2d').getImageData(0, 0, 640, 480).data;
        $("#use_image").click(function() {
        let $form = $(".image_submit_form");
        let form_data = new FormData($form[0]);

            $.ajax({
                url: $form.attr('action'),
                type: $form.attr('method'),
                dataType: 'json',
                data: 'image': JSON.stringify(data_pixel),
            }).done(function(data) {
                console.log(data['response']);
            });
        });

此外,添加以下脚本以避免ajax后出现csrf_token

// csrf code
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i].trim();
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    var csrftoken = getCookie('csrftoken');

    function csrfSafeMethod(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        }
    });

在视图中:

def img_submit(request):
    data_image = request.POST.get('image')
    data_image_parse = json.loads(data_image) # parse JSON.stringify and would be a dictionary
    data_image = list(data_image_parse.values()) # convert to list and would be length of 640 * 480 * 4
    image = np.array(data_image).reshape(480, 640, 4) # here is your image data and you can save it
    response = {}
    response['response'] = 'whatever you want to say' 
    return JsonResponse(response)

请注意,Django的DATA_UPLOAD_MAX_MEMORY_SIZE为2.5MB,但是您可以在设置中更改此默认设置。
希望这会有所帮助!