在Flask的视图函数中,如何处理文件过大导致的异常?

后端开发 2026-07-08

我想在我的视图中捕获RequestEntityTooLarge,但我的自定义错误处理程序却被调用。

我的 "movie.py" 有一个用于创建新电影条目的路由。

from flask import (
    Blueprint, render_template, request, flash, redirect, url_for, current_app
)

from datetime import datetime
from flask_login import login_required
from moviedb.shared.models import db
from moviedb.movies.models import Movie
from sqlalchemy.exc import IntegrityError
from moviedb.shared.utils import upload_file, delete_old_file
from werkzeug.exceptions import RequestEntityTooLarge

bp = Blueprint('movie', __name__)

@bp.route('/create', methods=('GET', 'POST'))
@login_required
def create():
    if request.method == 'POST':
        request.max_content_length = current_app.config['MAX_UPLOAD_SIZE']
        title = request.form['title']
        subtitle = request.form['subtitle']
        description = request.form['description']
        author = request.form['author']
        release = request.form['release']
        error = None
        new_filename = None

        if not title:
            error = {'movie_create_invalid_title' : 'Title is required.' }

        if not subtitle:
            error = {'movie_create_invalid_subtitle': 'Subtitle is required.' }

        if not description:
            error = {'movie_create_invalid_description': 'Description is required.' }

        if not author:
            error = {'movie_create_invalid_author': 'Author is required.' }

        if not release:
            error = {'movie_create_invalid_release': 'Release is required.' }

        existing_movie = db.session.execute(db.select(Movie).where(Movie.title == title)).scalar()

        if existing_movie is not None:
            error = {'movie_create_movie_already_exists': f'The movie with the title {title} already exists.' }

        if error is not None:
            flash(error)
        else:
            try:
                new_filename = upload_file(request, 'image')
                release_date = datetime.strptime(release, '%Y-%m-%d')
                movie = Movie(title=title, 
                              subtitle=subtitle, 
                              description=description, 
                              author=author, 
                              release=release_date, 
                              image=new_filename)
                db.session.add(movie)
                db.session.commit()
            except ValueError as e:
                db.session.rollback()
                error = { 'movie_create_value_error' : f'A value error occured. {e}' }
            except IntegrityError as e:
                db.session.rollback()
                error = { 'movie_create_integrity_error' : f"A integrity error occured. {e.code}" }
            except RequestEntityTooLarge as e:
                db.session.rollback()
                error = { 'movie_create_request_entity_too_large' : f"The file is too large for upload. {e.code}"}
            else:
                return redirect(url_for('movie.index'))

            if error is not None:
                flash(error)

    return render_template('movie/create.html')

我的 "init.py" 把一切拼在一起。

from flask import Flask
from moviedb.login import login_manager
from moviedb.shared.models import db
from moviedb import auth, movie, download
from moviedb import error_handlers

def create_app():
    app = Flask(__name__)

    if app.config['DEBUG']:
        app.config.from_object('moviedb.default_settings')
    else:
        app.config.from_envvar('MOVIEDB_SETTINGS')

    app.register_error_handler(404, error_handlers.page_not_found)
    app.register_error_handler(405, error_handlers.method_not_allowed)
    app.register_error_handler(413, error_handlers.request_entity_too_large)

    login_manager.init_app(app)

    db.init_app(app)

    with app.app_context():
        db.create_all()

    app.register_blueprint(auth.bp)

    app.register_blueprint(movie.bp)
    app.add_url_rule('/', endpoint='index')

    app.register_blueprint(download.bp)
    app.add_url_rule('/uploads/<name>', endpoint="download_file", build_only=True)

    return app

if __name__ == '__main__':
    create_app()

我的 "error_handlers.py" 用来处理错误。

from flask import render_template

def page_not_found(e):
    return render_template('404.html'), 404

def method_not_allowed(e):
    return render_template('405.html'), 405

def request_entity_too_large(e):
    return render_template('413.html'), 413

我想要实现的是,在上传的文件太大时显示错误信息。

我该如何正确地实现呢?

解决方案

我通过这篇帖子找到了一个解决方案:

https://stackoverflow.com/a/23601025/26749427

我只是把下面这段代码加到了我的upload_file函数中:

        file.seek(0, os.SEEK_END)
        file_size = file.tell()
        file.seek(0, os.SEEK_SET)
        if file_size > current_app.config['MAX_UPLOAD_SIZE']:
            raise RequestEntityTooLarge()
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章