Flask中send_file配合表格图片滚动懒加载失效问题解决
解决Flask表格图片滚动懒加载问题
一、修复基础懒加载失效问题
你的懒加载不生效核心原因是img标签直接设置了src属性,浏览器会优先加载src指向的资源,懒加载插件根本无法拦截。按以下步骤修改:
1. 调整前端img标签代码
将src替换为懒加载插件识别的data-src,同时给src设置一个极小的空白占位图(用base64编码避免额外请求):
<td> <a href="#" data-toggle="modal" data-target="#imageModal{{ id }}"> <img data-src="{{ url_for('getLogImage', fn=id.zfill(12) ~ '.jpg') }}" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazy rounded" width="100px" height="100px"> </a> </td>
2. 正确配置lazyload插件
由于你的滚动容器是.scrollable-table(不是全局window),初始化时必须指定container参数,否则插件无法监听正确的滚动事件:
$(document).ready(function() { // 初始化懒加载,指定滚动容器并设置提前加载阈值 $("img.lazy").lazyload({ container: $('.scrollable-table'), threshold: 200 // 提前200px加载即将进入可视区域的图片 }); });
无需手动在scroll事件里重复调用lazyload,插件会自动监听容器的滚动事件
二、解决8万行DOM性能问题
即使修复了懒加载,8万行表格DOM会导致页面渲染极慢、CPU占用过高,必须配合虚拟滚动(只渲染可视区域内的行+少量缓冲行):
1. 改造表格结构
添加空白占位行模拟完整表格高度,避免滚动时出现空白:
<div class="scrollable-table" style="height:72vh; width:90vw; overflow:scroll;" id="scrollContainer"> <table id="logTable" class="table"> <thead class="sticky-top" style="background-color: #f8f9fa;"> <tr> <th>Date and time</th> <th>Image</th> </tr> </thead> <tbody id="tableBody"> <!-- 动态渲染的行放在这里 --> </tbody> <!-- 空白占位行,模拟完整表格高度 --> <tbody id="placeholderBody"> <tr style="height: {{ imgids|length * 120 }}px;"> <!-- 假设每行高度120px,根据实际调整 --> <td colspan="2"></td> </tr> </tbody> </table> </div>
2. 实现虚拟滚动逻辑
$(document).ready(function() { const container = $('#scrollContainer'); const tableBody = $('#tableBody'); const totalRows = {{ imgids|length }}; const rowHeight = 120; // 每行高度,需和实际渲染行高度一致 const bufferRows = 20; // 上下缓冲行数,避免滚动时闪屏 const imgData = {{ imgids|tojson }}; const dateData = {{ dateTime|tojson }}; // 渲染指定范围的行 function renderRows(start, end) { tableBody.empty(); for (let i = start; i < end; i++) { if (i >= totalRows) break; const id = imgData[i]; const dt = dateData[i]; const imgUrl = "{{ url_for('getLogImage', fn='') }}" + id.zfill(12) + '.jpg'; const row = ` <tr> <td>${dt}</td> <td> <a href="#" data-toggle="modal" data-target="#imageModal${id}"> <img data-src="${imgUrl}" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazy rounded" width="100px" height="100px"> </a> </td> </tr> `; tableBody.append(row); } // 重新初始化懒加载 $("img.lazy").lazyload({ container: container, threshold: 200 }); } // 计算当前可视范围的行 function calculateVisibleRows() { const scrollTop = container.scrollTop(); const startRow = Math.max(0, Math.floor(scrollTop / rowHeight) - bufferRows); const endRow = Math.min(totalRows, startRow + bufferRows * 2 + Math.ceil(container.height() / rowHeight)); renderRows(startRow, endRow); } // 初始化渲染 calculateVisibleRows(); // 监听滚动事件更新渲染 container.scroll(calculateVisibleRows); });
三、Flask后端优化(可选)
为了进一步提升图片加载速度,给接口添加安全校验和缓存控制:
from flask import send_file, request from werkzeug.utils import secure_filename import os @app.route('/getLogImage/') def getLogImage(): fileName = request.args.get('fn', None) if not fileName: return "Missing filename", 400 # 安全校验文件名,防止路径遍历攻击 safe_fn = secure_filename(fileName) img_path = os.path.join("D:/images/", safe_fn) if not os.path.exists(img_path): return "Image not found", 404 # 添加缓存控制,让浏览器缓存图片30天 return send_file(img_path, mimetype='image/jpg', cache_timeout=2592000)
内容的提问来源于stack exchange,提问作者sharkyenergy
相关产品推荐
相关产品推荐

