无法让图像上传与 Flask 和 JQuery 一起使用

Posted

技术标签:

【中文标题】无法让图像上传与 Flask 和 JQuery 一起使用【英文标题】:Can't get image upload to work with Flask and JQuery 【发布时间】:2021-12-14 19:47:27 【问题描述】:

以下代码允许您使用 AJAX 和 JQuery 从 Flask 提交表单并返回文本的变体:

from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('form.html')

@app.route('/process', methods=['POST'])
def process():

    email = request.form['email']
    name = request.form['name']

    if name and email:
        newName = name[::-1]

        return jsonify('name' : newName)

    return jsonify('error' : 'Missing data!')

if __name__ == '__main__':
    app.run(debug=True)
<!DOCTYPE html>
<html>
<head>
    <title>AJAX Example</title>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>

    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>

    <script src=" url_for('static', filename='js/form.js') "></script>
</head>
<body>
<div class="container">
    <br><br><br><br>
    <form class="form-inline">
      <div class="form-group">
        <label class="sr-only" for="emailInput">Email address</label>
        <input type="email" class="form-control" id="emailInput" placeholder="Email">
      </div>
      <div class="form-group">
        <label class="sr-only" for="nameInput">Name</label>
        <input type="text" class="form-control" id="nameInput" placeholder="First Name">
      </div>
      <button type="submit" class="btn btn-default">Submit</button>
    </form>
    <br>
    <div id="successAlert" class="alert alert-success" role="alert" style="display:none;"></div>
    <div id="errorAlert" class="alert alert-danger" role="alert" style="display:none;"></div>
</div>
</body>
</html>
$(document).ready(function() 

    $('form').on('submit', function(event) 

        $.ajax(
            data : 
                name : $('#nameInput').val(),
                email : $('#emailInput').val()
            ,
            type : 'POST',
            url : '/process'
        )
        .done(function(data) 

            if (data.error) 
                $('#errorAlert').text(data.error).show();
                $('#successAlert').hide();
            
            else 
                $('#successAlert').text(data.name).show();
                $('#errorAlert').hide();
            

        );

        event.preventDefault();

    );

);

但是当我稍微修改代码以对上传的文件名做同样的事情时,它就不起作用了。我所做的只是更改表单的类型,以便它接收文件,然后使它反转文件名而不是以前版本的输入文本。你知道我在这里做错了什么吗?

from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('form.html')

@app.route('/process', methods=['POST'])
def process():

    filename = request.files['file'].filename

    if filename:
        newName = filename[::-1]

        return jsonify('name' : newName)

    return jsonify('error' : 'Missing data!')

if __name__ == '__main__':
    app.run(debug=True)
<!DOCTYPE html>
<html>
<head>
    <title>AJAX Example</title>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>

    <!-- Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>

    <script src=" url_for('static', filename='js/form.js') "></script>
</head>
<body>
<div class="container">
    <br><br><br><br>
    <form method="POST" action='/process' enctype="multipart/form-data">
        <div>
          <label for="file">Choose file to upload</label>
          <input type="file" id="file" name="file">
        </div>
        <div>
          <button type="submit" class="btn btn-default">Submit</button>
        </div>
       </form>
    <br>
    <div id="successAlert" class="alert alert-success" role="alert" style="display:none;"></div>
    <div id="errorAlert" class="alert alert-danger" role="alert" style="display:none;"></div>
</div>
</body>
</html>
$(document).ready(function() 

    $('form').on('submit', function(event) 

        $.ajax(
            data : 
                
                file : $('#file')
            ,
            type : 'POST',
            url : '/process'
        )
        .done(function(data) 

            if (data.error) 
                $('#errorAlert').text(data.error).show();
                $('#successAlert').hide();
            
            else 
                $('#successAlert').text(data.name).show();
                $('#errorAlert').hide();
            

        );

        event.preventDefault();

    );

);

【问题讨论】:

【参考方案1】:

如果您使用 FormData 类型的对象来序列化和传输表单的数据,它应该可以工作。

$(document).ready(function() 
  $('form').submit(function(event) 
    let formData = new FormData(event.target);
    $.ajax(
      data: formData,
      type : 'POST',
      url : '/process',
      contentType: false,
      processData: false
    )
    .done(function(data) 
      if (data.error) 
        $('#errorAlert').text(data.error).show();
        $('#successAlert').hide();
       else 
        $('#successAlert').text(data.name).show();
        $('#errorAlert').hide();
      
    );
    event.preventDefault();
  );
);

【讨论】:

这似乎没有解决问题 - 与原始代码不同,它只是重定向到带有“JSON”、“原始数据”和“标题”的屏幕,而不是打印出反向原始页面中的文件名 @tewerty 对不起。修改了我的答案。 非常感谢 - 现在运行良好!请问这两行代码有什么区别,为什么? @tewerty contentType: false 防止 jQuery 自动设置内容类型。 processData: false 防止将数据转换为字符串。这意味着使用了 FormData 对象的设置。 我也可以问一下 event.preventDefault() 在这里完成了什么?

以上是关于无法让图像上传与 Flask 和 JQuery 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 JQuery AJAX 将图像 + 文本数据上传到 Laravel

jquery文件上传在一篇文章中发送所有文件

通过python脚本将图像上传到python flask API [重复]

结合jQuery文件上传和表单到mysql

如何在Python框架Flask中将图像文件从表单上传到数据库

如何在 Elastic Beanstalk 中配置 Flask 应用程序以使用 S3 保留用户上传的图像文件