Flask生成图片二维码报ValueError版本无效错误的解决方法咨询
解决Flask生成图片二维码时的Invalid version错误
问题详情
开发Flask应用实现图片转二维码功能时,出现如下报错:
Failed to load resource: the server responded with a status of 500 (INTERNAL SERVER ERROR) File AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\main.py", line 160, in make self.best_fit(start=self.version) File AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\main.py", line 232, in best_fit self.version = bisect_left( File AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\main.py", line 115, in version util.check_version(value) File AppData\Local\Programs\Python\Python311\Lib\site-packages\qrcode\util.py", line 185, in check_version raise ValueError(f"Invalid version (was {version}, expected 1 to 40)") ValueError: Invalid version (was 41, expected 1 to 40)
相关代码
Python后端代码
def generate_qr_image(data): memory = BytesIO() qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4) qr.add_data(data) qr.make(fit=True) img = qr.make_image(fill_color='white', back_color='#282d39') img = img.convert("RGBA") background = Image.new("RGBA", img.size) qr_code = Image.alpha_composite(background, img) qr_code.save(memory, format="PNG") memory.seek(0) base64_img = "data:image/png;base64," + \ b64encode(memory.getvalue()).decode('ascii') return base64_img @app.route('/qr_image_select', methods=['POST']) def image_select(): if 'image-input' in request.files: image_file = request.files['image-input'] if image_file: image_data = image_file.read() encoded_string = base64.b64encode(image_data).decode('ascii') qr_image_data = generate_qr_image(encoded_string) return render_template('qr_image.html', data=qr_image_data) return "No image file selected."
HTML前端代码
<form action="/qr_image_select" method="POST" enctype="multipart/form-data"> <input type="file" name="image-input"> <button type="submit" class="button">Select File</button> </form> <br><br> {% if data %} <div class="qrcode"> <img src="{{ data }}" alt="QR_CODE"> <p>qr_code has been generated!</p> </div> {% endif %}
解决办法
1. 限制上传图片的大小
二维码容量有限,Version 40是QR码的最大版本,对应纠错等级L时最多只能存储2953个字符。图片转base64后体积会增加约33%,稍大的图片就会超出字符上限,导致库尝试使用不存在的Version 41。
在后端添加文件大小限制:
import os @app.route('/qr_image_select', methods=['POST']) def image_select(): if 'image-input' in request.files: image_file = request.files['image-input'] if image_file: # 限制图片大小为100KB(可按需调整) image_file.seek(0, os.SEEK_END) file_size = image_file.tell() image_file.seek(0) if file_size > 100 * 1024: return "图片大小不能超过100KB" image_data = image_file.read() encoded_string = base64.b64encode(image_data).decode('ascii') qr_image_data = generate_qr_image(encoded_string) return render_template('qr_image.html', data=qr_image_data) return "未选择图片."
2. 改用URL托管图片(推荐方案)
直接存储图片base64编码到二维码低效且受限,更合理的方式是将上传图片保存到服务器或云存储,生成可访问的URL,再将URL存入二维码,字符数极少,完全不会触发版本超限问题。
修改后端代码实现:
import os from werkzeug.utils import secure_filename from flask import url_for # 配置上传文件夹 app.config['UPLOAD_FOLDER'] = os.path.join(app.root_path, 'static', 'uploads') os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) # 允许的图片格式 ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'} def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.route('/qr_image_select', methods=['POST']) def image_select(): if 'image-input' in request.files: image_file = request.files['image-input'] if image_file and allowed_file(image_file.filename): filename = secure_filename(image_file.filename) file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) image_file.save(file_path) # 生成可公开访问的URL image_url = url_for('static', filename=f'uploads/{filename}', _external=True) qr_image_data = generate_qr_image(image_url) return render_template('qr_image.html', data=qr_image_data) return "未选择有效图片."
3. 调整QRCode初始化参数
如果坚持直接存储base64编码,可以不指定初始version,让库自动选择合适版本(但本质仍受内容大小限制):
qr = qrcode.QRCode( error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4 )
此方法仅能解决小图片的问题,大图片仍会触发版本超限错误。
内容的提问来源于stack exchange,提问作者luknow3
相关产品推荐
相关产品推荐

