通过 AJAX 上传文件在 Flask 端返回空字典

Posted

技术标签:

【中文标题】通过 AJAX 上传文件在 Flask 端返回空字典【英文标题】:Posting file upload via AJAX returns empty dictionary on Flask side 【发布时间】:2021-12-09 12:13:27 【问题描述】:

我有一个 Flask 应用程序在我添加登录功能之前一直在工作。我遇到的问题是我有一个用户可以上传文件的模式。

html

<p>Upload Photo</p>
          <form method="POST" name="upload_pic" id="upload_pic" enctype="multipart/form-data">
          <input type="file" class="custom-file-input" name="exampleInputFile" id="exampleInputFile" aria-describedby="fileHelp">
          <label class="custom-file-label" for="exampleInputFile">
           Select file...
        </label>
            <button type="button" class="btn btn-success" data-dismiss="modal" id="AddNotesSubmit">Submit</button>

然后AJAX调用上传文件:

// add notes post
  $('#AddNotesSubmit').on('click', function(e) 

      var notes = $("#note_text").val();
      var schedule_id = $("#noteSchID").text();

      console.log(notes);

      e.preventDefault();
      $.ajax(
          type: "POST",
          url: "/",
          data:  AddNotes: "", schedule_id: schedule_id, notes: notes ,
          success:function(response)
             $('#response').text(JSON.stringify(response));
          
      );

      var fullPath = $("#exampleInputFile").val();
      var filename = fullPath.replace(/^.*[\\\/]/, '');
      const form = $('#upload_pic')[0];
      const pic = new FormData(form);

      console.log(form);
      console.log(pic);
      console.log(filename);

      if (filename != '') 
        $.ajax(
            type: "POST",
            url: "/upload_pic",
            data: pic,
            processData: false,  // tell jQuery not to process the data
            contentType: false   // tell jQuery not to set contentType
        );
      


      $('#modalAddNotes').modal('hide');
  );

  );

最后是我用来调试的 Flask 代码:

@app.route('/upload_pic', methods=['POST'])
def upload_pic():
        print(' request.files: %s' %request.files)
        files = request.files.get('files[]')
        print(' files: %s' %files)

python端的命令行输出为:

request.files: ImmutableMultiDict([])
files: None

所以它返回一个空字典。以前,当我使用:

uploaded_pic = request.files['exampleInputFile']

它有效,但现在包含该代码会引发 400 错误,因为 'exampleInputFile'request.files 字典中的无效键。我从路由中删除了@login_required,它没有改变任何东西。

【问题讨论】:

request.files.get('exampleInputFile') 你从哪里得到files[]?这不是文件输入的名称。 在另一个线程中提到,如果是多文件上传,'files[]' 应该返回所有已上传文件的列表... get('') 中的'exampleInputFile' 返回空字典出现同样的错误。 参数必须匹配文件输入的name="xxx" 属性。那个“其他线程”大概有name="files[]" 感谢您的反馈。我知道 name = 'XXX' 必须匹配 request.files['XXX'] 但是当我这样做时,我收到此错误:werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent an request that this服务器无法理解。 KeyError:'exampleInputFile' 【参考方案1】:

在我看来,很难看出您的代码为什么不起作用。在您的示例中,表单标签未关闭。此外,您没有描述您的 javascript 代码是如何执行的。尽管我假设您使用的是单击事件,但我使用提交事件测试了您的代码。我得出的结论是代码有效。

这是我用于测试的变体:

  <p>Upload Photo</p>
    <form method="POST" name="upload_pic" id="upload_pic" enctype="multipart/form-data">
      <input type="file" class="custom-file-input" name="exampleInputFile" id="exampleInputFile" aria-describedby="fileHelp">
      <label class="custom-file-label" for="exampleInputFile">
       Select file...
      </label>
      <button type="submit" class="btn btn-success" data-dismiss="modal" id="AddNotesSubmit">Submit</button>
    </form>

    <script
      src="https://code.jquery.com/jquery-3.6.0.min.js"
      integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
      crossorigin="anonymous"></script>
    <script type="text/javascript">
      $(document).ready(function() 
        $('form[name="upload_pic"]').submit(function(event) 
          event.preventDefault();
          const form = event.target;
          const formData = new FormData(form);
          $.ajax(
            type: 'POST',
            url: '/upload_pic',
            data: formData,
            processData: false,
            contentType: false
          ).done((data) => 
            console.log(data);
          )
        );
      );
    </script>
@app.route('/upload_pic', methods=['POST'])
def upload_pic():
    if 'exampleInputFile' in request.files:
        file = request.files['exampleInputFile']
        if file.filename != '':
            # handle file here!
            return jsonify(success=True)
    return jsonify(success=False)

【讨论】:

我为该事件添加了完整的 js 代码。上半部分处理模态提交的文本部分,它工作正常。 谢谢!当我为它制作一个带有新路线的空白页面时,你的代码就工作了。是页面中的其他东西弄乱了它。 @TonyD。对不起,我在你写的代码中找不到任何错误。恐怕我帮不了你。

以上是关于通过 AJAX 上传文件在 Flask 端返回空字典的主要内容,如果未能解决你的问题,请参考以下文章

.Net之使用Jquery Ajax通过FormData对象异步提交图片文件到服务端保存并返回保存的图片路径

深入浅出Flask:使用ajax与后端交互

用flask做了个文件管理,上传速度太慢了

Flask框架:如何运用Ajax轮询动态绘图

Flask框架:运用Ajax轮询动态绘图

如何通过 AJAX 使用 Flask-WTForms CSRF 保护?