python-3.x - 通过 enctype ="multipart/form-data"上传多个文件,第一个上传的文件大小始终为0,其余都可以

标签 python-3.x forms flask python-requests

我正在使用表单 enctype="multipart/form-data"和 Flask 将多个文件上传到服务器。

我的问题是选择的第一个文件始终为空(0 大小)。其余所有选定的文件都以正确的大小上传,只有第一个选定的文件以 0 的大小上传,使其无法使用。

这看起来与以下问题相关:File is empty after saving flask uploads

查看 bukman 的评论:

“我意识到,当您在表单中使用“多个”属性时,Flask 有一个习惯,即包含一个与其中一个文件附件(通常是第一个附件)名称和详细信息完全相同的空文件上传”

这真的是真的吗?因为这似乎正是发生在我身上的事情,对我来说这是一种非常奇怪的行为方式。

这是我的表格:


<form method="post" enctype="multipart/form-data">

   <table class="center">

      <tr>
          <td class="font-weight-bold" align="left">file.tcx:</td>
          <td class="font-weight-bold" align="left"><input type="file" 
           name="tcxfiles[]" multiple class="form-control-file"/></td>
      </tr>
   </table>


  <div style="text-align: center"><input class="btn btn-primary btn-lg" 
   type="submit">
  </div>
</form>

在 Python/Flask 中我以这种方式处理文件:

files = request.files.getlist("tcxfiles[]")

        for each_file in files:
            if each_file and allowed_file(each_file.filename):
                filename = secure_filename(each_file.filename)
                each_file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

allowed_file 是一个函数,我仅使用它来过滤上传的文件并仅允许 .tcx 文件 secure_file_name函数是确保文件名安全的函数。

两者均从 flask 文档中复制:

https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/

如上所述,如果我上传多个文件,第一个文件将以长度 0 存储,其他文件以正确的长度存储。

如果我只选择一个文件,那么它会与文件 0 一起存储。

我的flask版本是1.1.1

>>> import pkg_resources
>>> pkg_resources.get_distribution('flask').version
'1.1.1'

任何提示都会有用,因为我正在挠头,试图理解这种行为。

预期结果是所有上传的文件都具有正确的大小,而不是始终有一个文件大小为 0

最佳答案

我尝试重现这个场景。我可以上传多个图像文件,没有任何错误。

目录结构:

.
├── app.py
├── requirements.txt
├── static
│   └── uploads
└── templates
    └── file_upload.html

requirements.txt:

Click==7.0
Flask==1.1.1
itsdangerous==1.1.0
Jinja2==2.10.1
MarkupSafe==1.1.1
pkg-resources==0.0.0
Werkzeug==0.15.5

app.py:

import os
from flask import Flask, flash, request, redirect, url_for, render_template
from werkzeug.utils import secure_filename

UPLOAD_FOLDER = os.path.join('static', 'uploads')
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        files = request.files.getlist("multiple_files[]")
        filenames = []
        for file in files:
            if file and allowed_file(file.filename):
                filename = secure_filename(file.filename)
                file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
                filenames.append(filename)
        flash("Uploaded files: {}".format(", ".join(filenames)))
    return render_template("file_upload.html")

file_upload.html:

<!doctype html>
<html>
<head>
  <title>Upload Multiple Files</title>
</head>
<body>
  {% with messages = get_flashed_messages() %}
  {% if messages %}
  <ul class=flashes>
    {% for message in messages %}
    <li>{{ message }}</li>
    {% endfor %}
  </ul>
  {% endif %}
  {% endwith %}
  <h1>Upload Multiple Files</h1>
  <form method="post" enctype="multipart/form-data" action={{url_for("upload_file")}}>
    <input type="file" name="multiple_files[]" multiple>
    <input type="submit" value="Upload">
  </form>
</body>
</html>

屏幕截图:

上传两张图片之前:

before uploading

上传两张图片后:

after uploading multiple files

ls -l 表示第一个文件不为空。我可以从 /static/uploads 文件夹中查看这两个图像。

关于python-3.x - 通过 enctype ="multipart/form-data"上传多个文件,第一个上传的文件大小始终为0,其余都可以,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57490511/

相关文章:

python - 循环识别素数和非素数生成错误输出

javascript - 使用 PHP 将简单的 HTML 表单写入 SQL DB,遭到机器人攻击

css - 是否可以仅使用 CSS 更改修改后的输入字段的样式?

Javascript form.submit() 在 Firefox 中不工作

python - 如何在 YAML 中指定始终使用 dictConfig 在项目文件夹中创建日志文件?

python - 如何在 map 函数中使用 strip

python - 具有至少 1 个唯一列值的随机 DataFrame 样本

python - 没有名为 flask.ext.wtf 的模块

zend-framework - 使用 Flask 或 Express 时如何不每次都重启服务器?

flask - 为什么要在创建应用实例之前访问应用路由