【问题标题】:How to send canvas data from javascript to django with ajax如何使用 ajax 将画布数据从 javascript 发送到 django
【发布时间】:2019-10-18 13:58:22
【问题描述】:

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

我正在使用 webrtc 来触发网络摄像头。我很难用 js 本身保存数据,并在某处读到仅靠 js 是不可能的。所以我现在正在尝试使用 ajax 将数据发送到 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 保存图像,但我想如果我能以某种方式将画布数据转换为 jpeg 或 png 然后将其发送到 python,那将很容易。我也不明白为什么我们必须将画布数据转换为 base64。我们不能将其转换为 png 吗?

请帮助我。 谢谢

[编辑1]

pythonviews.py

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

【问题讨论】:

    标签: javascript python ajax django


    【解决方案1】:

    我正在使用 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,但您可以在设置中更改此默认值。
    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 我仍然得到相同的结果。现在这段代码的输出是csrfmiddlewaretoken。我已经编辑了问题以添加 django views.py。
      • 我不确定,如何将画布数据转换为 jpeg 或 png,然后将其发送到 python。请帮帮我。
      • 如果您的 dataURL 未定义,那么我发现您有错误
      • 我的代码似乎没有出现任何错误。但问题是它没有向 python 返回任何东西
      • 在使用前尝试console.log(dataURL)或使用调试器查看ajax时刻的真实值...你必须确定!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-12
      • 1970-01-01
      • 1970-01-01
      • 2022-10-08
      • 1970-01-01
      • 1970-01-01
      • 2011-06-02
      相关资源
      最近更新 更多