如何使用Flask Socket.IO传输图片?现有代码无法显示图片求帮助
Flask Socket.IO 图片传输问题解决
我是Flask Socket.IO的新手,正在尝试实现通过Flask Socket.IO传输图片的方案。使用application.py从项目目录发送已保存的图片,application1.js接收二进制图片数据,index.html用于展示图片,但页面上完全看不到图片。相关代码如下:
application.py
from flask_socketio import SocketIO, emit from flask import Flask, render_template, url_for, copy_current_request_context from random import random from time import sleep from threading import Thread, Event __author__ = 'slynn' app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' app.config['DEBUG'] = True socketio = SocketIO(app, async_mode=None, logger=True, engineio_logger=True) #random number Generator Thread thread = Thread() thread_stop_event = Event() def randomNumberGenerator(): print("Making random numbers") while not thread_stop_event.isSet(): with open('savedImage.jpg', 'rb') as f: image_data = f.read() socketio.emit('my_response', {'image': image_data}, namespace='/test') socketio.sleep(2) @app.route('/') def index(): return render_template('index.html') @socketio.on('connect', namespace='/test') def test_connect(): global thread print('Client connected') if not thread.is_alive(): print("Starting Thread") thread = socketio.start_background_task(randomNumberGenerator) @socketio.on('disconnect', namespace='/test') def test_disconnect(): print('Client disconnected') if __name__ == '__main__': socketio.run(app)
application1.js
$(document).ready(function(){ var socket = io.connect('http://' + document.domain + ':' + location.port + '/test'); var numbers_received = []; socket.on('my_response', function(msg) { let arrayBufferView = new Uint8Array(msg['image']); console.log(arrayBufferView); var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } ); //maintain a list of ten numbers var img_url = URL.createObjectURL(blob); console.log(img_url); document.getElementById("img_show").src = img_url; }); });
index.html
<!DOCTYPE html> <html> <head> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/4.4.1/socket.io.min.js"></script> <script src="static/jscript/application1.js"></script> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> </head> <body> <div class="container"> <div class="jumbotron"> <h1>Asynchronous Flask Communication</h1> <p>Random numbers generated by the Flask server will appear below, asynchronously.</p> <p>Details <a href='https://www.shanelynn.ie/asynchronous-updates-to-a-webpage-with-flask-and-socket-io/' target='_blank'>here.</a></p> </div> </div> </div> <div class="container" id="content"> <div class="row"> <h3>Image:</h3> <div id="img_show"> </div> <!-- /#log --> </div> </div> </body> </html>
问题原因及修复方案
1. HTML标签错误
页面中用来展示图片的是<div id="img_show"></div>,但src是<img>标签专属属性,div标签无法通过设置src显示图片。需将div替换为img标签:
<div class="container" id="content"> <div class="row"> <h3>Image:</h3> <img id="img_show" alt="传输的图片" /> </div> </div>
2. 二进制数据传输格式问题
Flask Socket.IO直接将bytes类型图片数据放入字典发送时,会因JSON不支持二进制数据被错误序列化,前端无法解析出正确内容。提供两种修复方式:
方式一:Base64编码传输(兼容性更好)
修改application.py,导入base64并将图片数据编码为Base64字符串:
# 新增导入 import base64 def randomNumberGenerator(): print("Making random numbers") while not thread_stop_event.isSet(): with open('savedImage.jpg', 'rb') as f: # 将二进制数据编码为Base64字符串 image_data = base64.b64encode(f.read()).decode('utf-8') socketio.emit('my_response', {'image': image_data}, namespace='/test') socketio.sleep(2)
修改application1.js,直接用Base64字符串生成Data URL设置图片src:
socket.on('my_response', function(msg) { // 构造Data URL赋值给img标签 document.getElementById("img_show").src = 'data:image/jpeg;base64,' + msg.image; });
方式二:直接发送二进制数据
修改application.py,将二进制数据作为单独参数发送,并指定binary=True:
def randomNumberGenerator(): print("Making random numbers") while not thread_stop_event.isSet(): with open('savedImage.jpg', 'rb') as f: image_data = f.read() # 直接发送二进制数据,指定binary=True socketio.emit('my_response', image_data, namespace='/test', binary=True) socketio.sleep(2)
修改application1.js,接收二进制数据并处理:
socket.on('my_response', function(msg) { let arrayBufferView = new Uint8Array(msg); var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } ); var img_url = URL.createObjectURL(blob); document.getElementById("img_show").src = img_url; });
验证
修改完成后,确保项目目录下存在savedImage.jpg,启动Flask应用,访问页面即可看到图片每隔2秒更新一次。
内容的提问来源于stack exchange,提问作者Sourav Chakraborty
相关产品推荐
相关产品推荐

