简体   繁体   English

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

[英]How to send canvas data from javascript to django with ajax

I am working on a django application where the user can trigger the webcam and capture a photo. 我正在开发一个django应用程序,用户可以在其中触发网络摄像头并捕获照片。 This photo is saved in a canvas. 这张照片保存在画布中。 I want to send this image to django views, through which, the image can be saved inside the django server. 我想将此图像发送到django视图,通过它可以将图像保存在django服务器中。

I am using webrtc to trigger the webcam. 我正在使用webrtc触发网络摄像头。 I was having a hard time saving the data with js itself and read somewhere that this is not possible with js alone. 我很难用js本身来保存数据,并且在某个地方读到单独使用js无法实现这一点。 So I am now trying to send te data to python using ajax but am not able to. 所以我现在正尝试使用ajax将te数据发送到python,但无法这样做。 I am a beginner with working with canvas and ajax so, a detailed explanation will be helpful. 我是使用canvas和ajax的初学者,因此,详细的说明会有所帮助。

I tried working with these answers, but none of them seemed to help 我尝试使用这些答案,但似乎都没有帮助

Send canvas image data (Uint8ClampedArray) to Flask Server via Ajax 通过Ajax将画布图像数据(Uint8ClampedArray)发送到Flask Server

Can't send data back to Django from JS AJAX 无法将数据从JS AJAX发送回Django

here is my code so far 到目前为止,这是我的代码

html template 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>

Not sure if a form is needed for use_image to send data to python. 不知道use_image是否需要use_image将数据发送到python。

javascript code 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');
            });
        });
    });

});

I am pretty sure I have messed up the ajax part. 我很确定自己搞砸了ajax部分。

I still have not written any code to save the image with python, but I am guess that will be easy if I can somehow convert the canvas data to a jpeg or png and then send it to python. 我仍然没有编写任何代码来使用python保存图像,但是我想如果我能以某种方式将画布数据转换为jpeg或png然后将其发送到python,这将很容易。 I also did not understand why we have to convert canvas data to base64. 我也不明白为什么我们必须将画布数据转换为base64。 Cant we just convert that to png? 不能将其转换为png吗?

Please help me. 请帮我。 Thank you 谢谢

[EDIT1] [EDIT1]

python views.py python views.py

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

Maybe you code works fine but this is critical : 也许您的代码工作正常,但这很关键:

 ...


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

You cant create object with two same key access. 您不能使用两个相同的键访问来创建对象。 Even no need to inject twice time same data. 甚至无需注入两次相同的数据。

Remove JSON.stringify line and then try again! 删除JSON.stringify行,然后重试! I already done this with websocket i don't see reason for not working! 我已经使用websocket完成了此操作,但看不到无法正常工作的原因!

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

Also try : 也可以尝试:

.toDataURL("image/png")

Check connection did work. 检查连接是否正常。

Post full errors log ! 发布完整的错误日志! Maybe you have permission bugs if you wanna do it programmability with no user request (click). 如果您想在没有用户请求(单击)的情况下进行可编程性设置,则可能会遇到权限错误。

I fount it ! 我找到它了!

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
            })

I'm sending the rgba pixels array to django views with ajax. 我正在使用ajax将rgba像素数组发送到django视图。
In your case, the code would like: 在您的情况下,代码需要:

        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']);
            });
        });

Besides, add below scripts to avoid the csrf_token after ajax 此外,添加以下脚本以避免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);
            }
        }
    });

In views: 在视图中:

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)

Notice that the django has DATA_UPLOAD_MAX_MEMORY_SIZE of 2.5MB but you can change this default in settings. 请注意,django的DATA_UPLOAD_MAX_MEMORY_SIZE为2.5MB,但是您可以在设置中更改此默认值。
Hope this helps! 希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM