0

我正在使用 Flask-Uploads 来处理 Web 应用程序中的图像上传。该网络应用程序仅接受 JPEG 图像,但似乎 Flask-Uploads 仅通过检查文件扩展名来强制执行此操作。

例如,我可以通过将文件名从更改为来轻松地颠覆这一点,myfile.txt文本myfile.jpg文件myfile.txt将被错误地接受为 JPEG 图像。

我如何确保上传到我的网络应用程序的文件实际上是内容的 JPEG 文件,而不仅仅是文件扩展名?

这是一个演示我正在尝试做的事情的最小实现(不包括模板):

# __init__.py

from flask import Flask
from flask_uploads import UploadSet, configure_uploads, IMAGES
from config import Config

app = Flask(__name__)
app.config.from_object(Config)

photos = UploadSet("photos", IMAGES)
configure_uploads(app, photos)

from app import routes
# routes.py

import os
from flask import redirect, render_template, send_from_directory, url_for
from flask_uploads import UploadNotAllowed
from app import app, photos
from app.forms import PhotoForm


@app.route('/', methods=["GET", "POST"])
def index():
    form = PhotoForm()
    if form.validate_on_submit():
        try:
            filename = photos.save(form.photo.data)
            return redirect(url_for("uploaded_file", filename=filename))
        except UploadNotAllowed:
            print("UploadNotAllowed!")
            redirect(url_for("index"))
    return render_template("index.html", form=form)


@app.route("/uploads/<filename>")
def uploaded_file(filename):
    directory = os.path.join(os.getcwd(), app.config["UPLOADED_PHOTOS_DEST"])
    return send_from_directory(directory, filename)

# forms.py

from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileRequired
from wtforms import SubmitField


class PhotoForm(FlaskForm):
    photo = FileField(validators=[FileRequired()])
    submit = SubmitField("Upload")
# config.py

import os


class Config(object):
    SECRET_KEY = os.environ.get("SECRET_KEY")
    UPLOADED_PHOTOS_DEST = "uploads"
    UPLOADED_PHOTOS_DENY = ["bmp", "gif", "png", "svg"]

4

1 回答 1

0

您可以导入UploadSet和 - 如文档字符串中所述 - 覆盖该file_allowed方法,例如创建自己的类,继承自UploadSet.

然后,您可以选择几个可以检测类型的 Python 库之一,例如https://github.com/ahupp/python-magic

PS:Flask-Uploads自 2020 年 2 月起就坏了,至少 PyPi 包。我创建了一个 fork,它是一个替代品,可通过https://pypi.org/project/Flask-Reuploaded/获得

于 2020-07-02T13:51:07.823 回答