Flask集成OpenCV扫码器重定向功能失效问题求助
问题原因
你在gen()生成器里返回redirect('/output/')完全无效——这个生成器是用来输出视频流帧数据的,对应的HTTP响应是multipart/x-mixed-replace类型,前端用<img>标签加载该流,根本不会处理重定向指令。而且生成器里的return只会终止生成器,不会触发页面跳转。另外全局变量output在多请求场景下会出现数据冲突,不适合用来存储扫码结果。
解决方案
要实现扫码成功后跳转,得让前端感知到扫码完成,再由前端主动发起跳转。这里用前端轮询检查的方式最容易实现,具体步骤如下:
1. 修改后端代码
from flask import Flask, render_template, Response, redirect, url_for, session, jsonify import io import cv2 import sys from pyzbar import pyzbar app = Flask(__name__) # 必须设置secret_key才能使用session app.secret_key = 'your_random_secret_key' # 替换成自定义的随机字符串 @app.route('/output/') def output(): # 从session获取扫码结果,无结果则返回扫码页面 barcode_data = session.get('barcode_data') if not barcode_data: return redirect(url_for('index')) return f"扫码结果:{barcode_data}" @app.route('/scanner') def index(): # 进入扫码页时清空旧的扫码结果 session.pop('barcode_data', None) return render_template('scanner.html') def gen(): vc = cv2.VideoCapture(0) while True: read_return_code, frame = vc.read() if not read_return_code: break og = frame.copy() # 保留原帧用于解码,避免被绘图操作修改 cv2.rectangle(frame,(200,170),(450,330),(0,255,100),7) frame = cv2.flip(frame, 1) decode = pyzbar.decode(og) if decode: # 提取第一个条码的内容并转成字符串 barcode_data = decode[0].data.decode('utf-8') session['barcode_data'] = barcode_data vc.release() break # 终止生成器,停止视频流输出 if cv2.waitKey(1) & 0xFF == ord('q'): vc.release() break encode_return_code, image_buffer = cv2.imencode('.jpg', frame) io_buf = io.BytesIO(image_buffer) yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + io_buf.read() + b'\r\n') @app.route('/video_feed') def video_feed(): return Response( gen(), mimetype='multipart/x-mixed-replace; boundary=frame' ) # 新增接口,供前端查询扫码状态 @app.route('/check_scan') def check_scan(): return jsonify({ 'success': 'barcode_data' in session, 'data': session.get('barcode_data') }) if __name__ == '__main__': app.run(host='0.0.0.0', debug=True, threaded=False)
2. 修改前端HTML(scanner.html)
添加JavaScript定时查询后端,检测到扫码成功后自动跳转:
<html> <head> <style> body{ font-family: Verdana, sans-serif; } </style> <title>Scanner</title> </head> <body> <h1>Scanner</h1> <img src="{{ url_for('video_feed') }}"> <script> // 每500毫秒查询一次扫码状态 const checkInterval = setInterval(() => { fetch('/check_scan') .then(res => res.json()) .then(data => { if (data.success) { clearInterval(checkInterval); // 停止轮询 window.location.href = '/output/'; // 跳转到结果页 } }) .catch(err => console.error(err)); }, 500); </script> </body> </html>
关键改动说明
- 用
session替代全局变量存储扫码结果,避免多用户场景下的数据冲突 - 生成器
gen()在扫码成功后仅终止视频流,不再尝试返回无效的重定向 - 新增
/check_scan接口,供前端主动查询扫码状态 - 前端通过JavaScript轮询检测状态,主动触发页面跳转
内容的提问来源于stack exchange,提问作者Dom_ The
相关产品推荐
相关产品推荐

