【问题标题】:Submitting Picture to Backend through Invisible Javascript Form通过 Invisible Javascript Form 提交图片到后端
【发布时间】:2020-02-28 09:07:27
【问题描述】:

我创建了一个按钮,使用后台 JS 表单将图片文件上传到后端。 我确实具有单击图片按钮打开表单以上传图片的功能。 我用找到here 的 cat.jpg 进行了尝试。 我在后端使用烧瓶来检查它是否是批准的类型,然后将其上传到静态文件夹。我添加了一个简单的 print 语句,以查看该方法是否被调用。

看来我的问题在于 addEventListener 提交功能。它似乎没有被调用。我假设因为我没有使用表单制作提交按钮,这就是它没有被调用的原因。但是,输入引发了计算机天真,文件上传有自己的提交,所以我觉得在这种情况下应该正确调用提交函数。我可以得到任何指针,我对 JS 和 Ajax 很陌生!

我的 JS 代码:

document.getElementById('button-picture').addEventListener('click', function() {

    // Create a form to upload the picture behind the scenes
    var picture_form = document.createElement('form');
    picture_form.setAttribute('id', 'image_upload_form');
    picture_form.setAttribute('enctype', 'multipart/form-data');
    picture_form.setAttribute('method', 'POST');
    var input_tag = document.createElement('input');
    input_tag.setAttribute('type', 'file');
    input_tag.setAttribute('id', 'file_upload');
    input_tag.setAttribute('name', 'files');
    input_tag.setAttribute('multiple', true);
    picture_form.append(input_tag);

    // Upload the picture to the backend when it is submitted.
    picture_form.addEventListener("submit", function(e) {
      // Do I need this?
      e.preventDefault();
      var request = new XMLHttpRequest();
      request.open('POST', '/upload-images', true);
      request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
      request.setRequestHeader('ProcessData', false)
      var csrf_token = "{{ csrf_token() }}";
      request.setRequestHeader('X-CSRFToken', csrf_token);
      var form_data = new FormData(picture_form.input.files);
      request.send(form_data);
    });
    input_tag.click()


    // Add markup Code to display it.

}, false);

我的后端代码查看此 SO question 中提供的内容。 此外,更新代码以反映此 SO question 无济于事。


更新**,更改代码:


    // Create a form to upload the picture behind the scenes
    var picture_form = document.createElement('form');
    picture_form.setAttribute('id', 'image_upload_form');
    picture_form.setAttribute('enctype', 'multipart/form-data');
    picture_form.setAttribute('method', 'POST');
    var input_tag = document.createElement('input');
    input_tag.setAttribute('type', 'file');
    input_tag.setAttribute('id', 'file_upload');
    input_tag.setAttribute('name', 'files');
    input_tag.setAttribute('multiple', true);
    picture_form.append(input_tag);
    var submit_event = new Event('submit');
    picture_form.dispatchEvent(submit_event);

    // Upload the picture to the backend when it is submitted.
    picture_form.addEventListener("submit", function(e) {
      alert("Hello");
      // Do I need this?
      // e.preventDefault();
      var request = new XMLHttpRequest();
      request.open('POST', '/upload_images', true);
      var csrf_token = "{{ csrf_token() }}";
      request.setRequestHeader('X-CSRFToken', csrf_token);
      var form_data = new FormData(picture_form);
      request.send(form_data);
    });
    input_tag.click()

编辑 2:

【问题讨论】:

  • 使用隐藏表单向后端发送数据的动机是什么?
  • 适用于文章类型的编辑器,通过在编辑器中按图片按钮插入图片,无需重新加载页面或单独上传图片。

标签: javascript ajax flask


【解决方案1】:

要手动提交表单,您可以使用HTMLFormElement.submit() 方法。但这不会导致表单元素触发submit 事件。

在这种情况下,您需要创建一个 Event 对象并将其发送到您的表单上。如下。

var picture_form = document.createElement('form');
...
var submitEvent = new Event('submit');
picture_form.dispatchEvent(submitEvent);

这将触发submit 事件,并导致您的事件侦听器上的回调被调用。

但您的代码将在以下行中断:

var form_data = new FormData(picture_form.input.files);

FormData 构造函数接受 <form> 元素作为参数。不是单个输入,因为它是从 <form> 元素中提取的 key-value 对的集合。将行更改为以下内容:

var form_data = new FormData(picture_form);

还应删除您包含的 Content-Type 标头。 FormData 对象在使用XMLHTTPRequest 发送时会自动设置正确的标头。

编辑 由于您只使用文件选择提示让用户选择他们的图像,因此您需要监听不同的事件。特别是change 事件。

picture_form.addEventListener('change', function() {
  ...
});

只要输入的值发生更改,就会触发此事件。对于 <input type="file"> 元素,当用户选择文件时会发生这种情况。

这里不需要new Event('submit')dispatchEvent 方法,change 事件将由用户调用,不必手动分派。

【讨论】:

  • 好的,明白了。我确实让 FormData 发送表单(它似乎与正在发送的文件不符)。但是,即使进行了这些更改,它似乎也不起作用。
  • 你能说得更具体点吗?
  • 我仍然没有看到请求发生在后端。没有 POST 被注册,方法被调用。任何正在打印的东西。请参阅原始答案编辑以获取新代码。没有调用 alert("Hello")。
  • 啊,有道理。那么你需要在适当的时候触发submit 事件。现在您创建元素并调度事件,然后设置事件侦听器。没有先听,什么都不会发生。我不清楚用户如何让您知道他们已完成选择文件。他们只看到文件选择提示吗?还是有其他方式让您知道文件已处理完毕?
  • 所以我从我之前正在处理的一个 JS 项目中复制了代码,当这个人完成输入时它提交了,我意识到这不适用于这里。我猜难题是,当他们单击图片按钮时,它会打开我猜是操作系统特定的文件上传器。我不确定我是否有办法检测它的提交,这确实有效....hmmmm
猜你喜欢
  • 2010-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-22
  • 1970-01-01
  • 2019-04-19
相关资源
最近更新 更多