如何修复Flask应用中出现的405 Method Not Allowed报错?
问题修复方案
报错根因
你遇到的报错对应两个核心逻辑问题:
GET /predict HTTP/1.1 405:/predict路由仅配置了POST请求权限,你在POST处理完成后直接重定向回/predict地址,重定向默认触发GET请求,直接触发权限拦截。GET /display/ HTTP/1.1 404:首页渲染时没有给模板传递filename参数,img标签生成的请求路径缺少文件名参数,匹配不到路由。
除此之外还有三处隐藏逻辑错误会导致功能无法正常运行:
- 表单没有配置
enctype="multipart/form-data"属性,后端无法接收到上传的文件 - 调用
fcr函数时参数传反,无法正常读取测试图片进行人脸识别 - 识别结果图片保存时没有加后缀,展示接口无法正常读取文件
分步修改方案
1. 修改app.py
首先添加根uploads目录初始化逻辑,然后修改predict路由的返回逻辑,不要重定向到/predict,直接渲染首页并传递结果图片文件名:
import os from flask import Flask, flash, request, redirect, render_template, url_for, send_file import flask from werkzeug.utils import secure_filename import fcr_cv from fcr_cv import fcr app = Flask(__name__) app.secret_key = "secret key" app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 新增:初始化根uploads目录 ROOT_UPLOAD = os.path.join(os.getcwd(), 'uploads') os.makedirs(ROOT_UPLOAD, exist_ok=True) ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif']) def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS def validate_input(request: flask.Request): input = {} try: input["sample"] = request.files.getlist('sample') input["test"] = request.files.get("test") input["folder"] = request.form["folder"] except Exception as e: print(e) return False, input return True, input @app.route('/predict', methods=['POST']) def predict(): if request.method == 'POST': if 'sample' not in request.files: flash('No file part') return redirect(url_for('upload_form')) if 'test' not in request.files: flash('No test part') return redirect(url_for('upload_form')) is_valid, input = validate_input(request) if not is_valid: flash('Invalid input') return redirect(url_for('upload_form')) files = input["sample"] folder_name = input["folder"] sample_path = os.path.join(ROOT_UPLOAD, folder_name) os.makedirs(sample_path, exist_ok=True) for file in files: if allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(sample_path, filename)) file = input["test"] test_filepath = os.path.join(ROOT_UPLOAD, "test_image.jpg") if allowed_file(file.filename): file.save(test_filepath) # 修正:fcr参数顺序调换,第一个参数是测试图片路径,第二个是样本文件夹路径 target_image = fcr_cv.fcr(test_filepath, sample_path) flash('Image successfully uploaded and displayed below') # 修正:渲染首页并传递结果文件名 return render_template('upload.html', filename=target_image) else: flash('Allowed image types are -> png, jpg, jpeg, gif') return redirect(url_for('upload_form')) @app.route('/') def upload_form(): # 首次加载不传filename,避免生成空的display请求 return render_template('upload.html', filename=None) @app.route('/display/<filename>') def cv_display_image(filename): return send_file(os.path.join(ROOT_UPLOAD, filename), mimetype='image/jpeg') if __name__ == "__main__": app.run()
2. 修改upload.html
添加表单文件上传属性,修正标签顺序,添加图片展示判断逻辑:
<html> <head> <title>Python Flask Multiple Files Upload Example</title> </head> <body> <h2>Select file(s) to upload</h2> <!-- 新增enctype属性支持文件上传 --> <form class="form" action="{{ url_for('predict') }}" method="POST" enctype="multipart/form-data"> <div class="row"> <p class="label">Sample files</p> <input class="input" type="file" name="sample" multiple="true" autocomplete="off" required> </div> <div class="row"> <p class="label">Folder Name</p> <input type="text" name="folder" required> </div> <div class="row"> <p class="label">Test File</p> <input class="input" type="file" name="test" autocomplete="off" required> </div> <input type="submit" name="submit" value="Predict"> </form> <!-- 新增判断:只有有结果图片的时候才加载 --> {% if filename %} <div> <img src="{{ url_for('cv_display_image', filename=filename) }}"> </div> {% endif %} </body> </html>
3. 修改fcr_cv.py
修正结果图片保存逻辑,添加文件后缀:
# 其余代码不变,只修改imwrite和返回值行 cv2.imwrite('./uploads/target_image.jpg', image) return "target_image.jpg"
内容的提问来源于stack exchange,提问作者Sambam
相关产品推荐
相关产品推荐

