如何通过Flask向网页客户端发送桌面通知?现有实现存在异常
解决Flask中网页客户端通知的实现方案
winotify是Windows系统的本地通知库,代码在Flask服务器端运行时,自然只会在服务器所在的Windows机器上弹出通知,和网页客户端完全无关。要给网页用户推送通知,得用前端的Web Notification API配合Flask后端逻辑实现,以下是具体方案:
1. 前端基础实现(纯浏览器通知)
前端需要先获取用户的通知权限,之后才能触发通知。将以下JS代码放入Flask渲染的HTML模板(比如templates/index.html)中:
// 请求通知权限 async function requestNotificationPermission() { if (!("Notification" in window)) { alert("你的浏览器不支持通知功能"); return; } const permission = await Notification.requestPermission(); if (permission !== "granted") { alert("需要开启通知权限才能接收提醒"); } } // 触发通知 function showNotification(title, body) { if (Notification.permission !== "granted") return; new Notification(title, { body: body, // 可选:自定义通知图标 // icon: "/static/notification-icon.png" }); } // 页面加载时自动请求权限 window.onload = requestNotificationPermission;
2. 配合Flask后端触发通知
如果需要后端事件(比如文件下载完成)触发客户端通知,可选择以下两种方式:
方式一:短轮询(简单易上手)
前端定时向后端请求任务状态,当后端返回任务完成的信号时,触发通知。
后端Flask代码示例:
from flask import Flask, render_template, jsonify import time import threading app = Flask(__name__) # 模拟任务状态,实际项目可存在数据库/缓存中 task_done = False def simulate_file_download(): global task_done # 模拟下载耗时 time.sleep(10) task_done = True @app.route('/') def index(): # 启动模拟下载的线程 threading.Thread(target=simulate_file_download).start() return render_template('index.html') @app.route('/check-task-status') def check_task_status(): global task_done return jsonify({"done": task_done})
前端补充轮询逻辑:
// 每2秒检查一次任务状态 setInterval(async () => { const response = await fetch('/check-task-status'); const data = await response.json(); if (data.done) { showNotification("通知", "文件已下载完成"); // 任务完成后停止轮询 clearInterval(this); } }, 2000);
方式二:WebSocket(实时性更高)
如果需要低延迟的实时通知,用WebSocket替代轮询更高效,Flask可通过flask-socketio扩展实现:
- 先安装依赖:
pip install flask-socketio
- 后端代码:
from flask import Flask, render_template from flask_socketio import SocketIO, emit import time import threading app = Flask(__name__) app.config['SECRET_KEY'] = 'your-secret-key' socketio = SocketIO(app, cors_allowed_origins="*") def simulate_file_download(): time.sleep(10) # 向所有连接的客户端推送通知 socketio.emit('notification', { 'title': '通知', 'body': '文件已下载完成' }) @app.route('/') def index(): threading.Thread(target=simulate_file_download).start() return render_template('index.html') if __name__ == '__main__': socketio.run(app, debug=True)
- 前端WebSocket逻辑:
// 连接WebSocket服务 const socket = io(); // 监听后端推送的通知事件 socket.on('notification', (data) => { showNotification(data.title, data.body); });
注意事项
- 浏览器通知需要用户手动授权,必须先调用
Notification.requestPermission()获取权限。 - HTTPS协议下通知功能可正常使用;HTTP协议仅在本地开发环境(localhost)生效。
- 可自定义通知的图标、点击跳转行为等,具体参考Web Notification API的相关规范。
内容的提问来源于stack exchange,提问作者Elysian
相关产品推荐
相关产品推荐

