Flask+LayUI开发手记(八):通用封面缩略图上传实现
前一节做了头像上传的程序,应该说,这个程序编写和操作都相当繁琐,实际上,头像这种缩略图在很多功能中都会用到,屏幕界面有限,绝不会给那么大空间摆开那么大一个界面,更可能的处理,就是显示一个缩略图,然后点击图像,即弹出文件选择框,选择文件后,直接上传,并且将当前缩略图改为选后的图像。
这一节就来展示这种实现过程。当然,这个实现中的缩略图更新实际上是form表单编辑的一部分,本节只展示缩略图相关的部分。主要也包括Html、JS和后台实现三个部分。
html页面实现如下:
<form class="layui-form" id="tbedit-form" lay-filter="tbedit-form" action="" tbd-operate="list" style="width:98%;display:none"><div class="layui-form-item"><label class="layui-form-label">文章封面</label><div class="layui-input-block"><input type="text" class="layui-input layui-hide" id="upload" name="picture" opt-type="thumb" url-upload="/srv_thumbnail/article/" value="" /><img id="upload-thumb" src="/static/images/article.png" onerror="this.src='/static/images/article.png'" title="点击图片更换封面" width="100px" height="100px"></div></div>
</form>
在这个表单输入条目里,包括两个域,一个是input域,用于存储缩略图的文件路径,这个域是hide的,在界面上不会展示出来。新增记录时为空,编辑记录时以表单初始化方式将值初始化进来。
另一个域是缩略图显示域,src会随input域的值更新,从而显示出图像来。src属性设置了一个缺省图像,不过设不设都不会有用,因为表单初始化时,编辑时会更新为后台存储的缩略图文件名,在新增操作时,input域的值会置为空,此时图像域的文件名也是空,展示会出错。所以要设置上onerror属性,保证在出错时可以显示缺省的缩略图。
html的input值输入域和img图像显示域的id属性有一个隐含约定,即img图像域的id是值输入域的id加后缀‘-thumb',同时,这两个域必须是同层兄弟节点。这样的约定最大的好处,就是在同屏可以有多个表单中拥有多个同名id的缩略图。界面显示效果如下。
增强渲染,可以做一个组件库来实现,并且通过在当前的标准输入域里配置增加属性来实现参数配置。像上面的html的input域中就多出两项属性来:opt-type="thumb" url-upload="/srv_thumbnail/article/"。这第一个opt-type就是用来配置增强组件类型为thumbnail的,第一项url-upload配置上传服务的url。
应该说,Html页面其实就是一个空架子,用于配置必要的参数。要起作用,需要通过JS渲染。在系统实现时,layui的标准表单输入域是不够的,需要做很多增强组件,比如树型编辑域、日期域、富文本编辑域还有这个缩略图,都要进行增强渲染。缩略图组件thumb的JavaScript渲染代码如下:
//对富文本编辑域进行渲染
function render_thumb(options) {let iform = options.formId;let keyw_name = `#${iform} input[opt-type=thumb]`;$(keyw_name).each(function() {elem_render_thumb($(this));});
},//渲染输入组件缩略图
funtion elem_render_thumb(i_elem) {render_upload(i_elem);function render_upload(i_elem) {let n_elem = i_elem.attr('id');let n_thumb = n_elem + '-thumb';let i_thumb = i_elem.siblings('#' + n_thumb);let url_upld = i_elem.attr('url-upload');if (url_upld==null) {url_upld = '/srv_thumbnail/article';}let uploadInst = upload.render({elem: '#' + n_thumb,url: url_upld, size : 2000,acceptMime: 'image/*',before: function(obj){obj.preview(function(index, file, result){i_thumb.attr('src', result); // 图片链接(base64)});layer.msg('上传中', {icon: 16, time: 0});},done: function(rs){if(rs.success == 0){return layer.msg(rs.msg);}layer.msg(rs.msg);let src_file = rs.thumbfile + '?time=' + new Date().getTime();i_thumb.attr('src',src_file);i_elem.val(rs.thumbfile);},error: function(){layer.msg("上传失败");}});i_elem.on('change',function(e) {let img_file = i_elem.val() + '?time=' + new Date().getTime();i_thumb.attr('src',img_file);});}
}
第一段程序render_thumb是form级的,查找到指定form里所有拥有属性opt-type="thumb"的元素,然后逐个对其进行渲染,渲染元素的函数为elem_render_thumb。这段程序为了展示方便进行了修改,实际的组件库是采用layui.define方式定义的,分为在form和elem两个库中。
文件上传采用layui上传组件upload,将其与缩略图展示域绑定,点击图片自然就弹 出选择窗开始执行了。与上一节不同的是,这次的设置是选择文件后自动上传,而不是分两阶段提交,也没有进度条效果,失败后不再支持重传(这些复杂的实现其实没必要)。
然后,是python服务端的程序:
import logging,json,time
from PIL import ImageSRVDATA_UPLOAD = 'srvdata/uploads/'# srvdata缩略图上传服务
@app.route('/srv_thumbnail/<path:filepath>',methods=['POST'])
def srvdata_thumbnail(filepath):logging.debug('POST thumbnail srvdata....')if request.method == 'POST':avt = request.files.get('file')sour_file_name = avt.filenameextname = sour_file_name.split('.')[1]dest_filename = 'thumb_' + str(time.time()) + '.' + extnamesave_path = SRVDATA_UPLOAD + filepath + dest_filename#avt.save(save_path)img = Image.open(avt)rimg = img.resize((128,128))rimg.save(save_path)rs_data = {'success':1,'msg':'更新文章缩略图成功','thumbfile': '/' + save_path,'code':0}return json.dumps(rs_data)
服务端程序的主体流程就是上传文件并且将其缩小为128*128的缩略图文件并且存储。要注意在路由定义时,在路由定义后跟了文件存储的路径名。这个路由是在前端html的url-upload中定义的"/srv_thumbnail/article/",也就是说文件存储的路径为'/srvdata/uploads/article/’下。这样,一个可以在各处中使用的缩略图上传组件就完成了。
最后,强调一下,要保证文件名输入域的值和缩略图的src联动,那么在更改值时,就必须手动触发。由于表单初始化值都是统一的,并不会单独就某个域初始化。所以,初始化值后,需要加上如下代码(新增清空时也要加),这样处理后,上面缩略图渲染程序中的i_elem.on('change',function(e) {}就可以起作用了。
//form.val(iform,rsdata);
let keyw_name = `#${iform} input,#${iform} select,#${iform} textarea`;
$(keyw_name).trigger('change');
最后还是展示一下界面效果图:
相关文章:

Flask+LayUI开发手记(八):通用封面缩略图上传实现
前一节做了头像上传的程序,应该说,这个程序编写和操作都相当繁琐,实际上,头像这种缩略图在很多功能中都会用到,屏幕界面有限,绝不会给那么大空间摆开那么大一个界面,更可能的处理,就…...

低代码采购系统搭建:鲸采云+能源行业订单管理自动化案例
在能源行业数字化转型浪潮下,某大型能源集团通过鲸采云低代码平台,仅用3周时间就完成了采购订单管理系统的定制化搭建。本文将揭秘这一成功案例的实施路径与关键成效。 项目背景与挑战 该企业面临: 供应商分散:200供应商使用不同…...

android关于pthread的使用过程
文章目录 简介代码流程pthread使用hello_test.cppAndroid.bp 编译过程报错处理验证过程 简介 android开发经常需要使用pthread来编写代码实现相关的业务需求 代码流程 pthread使用 需要查询某个linux函数的方法使用,可以使用man 函数名 // $ man pthread_crea…...
Faiss vs Milvus 深度对比:向量数据库技术选型指南
Faiss vs Milvus 深度对比:向量数据库技术选型指南 引言:向量数据库的时代抉择 在AI应用爆发的今天,企业和开发者面临着如何存储和检索海量向量数据的重大技术选择。作为当前最受关注的两大解决方案,Faiss和Milvus代表了两种不同…...
慢慢欣赏linux 之 last = switch_to(prev, next)分析
last switch_to(prev, next); 为什么需要定义last作为调用switch_to之前的prev的引用 原因如下: struct task_struct * switch_to(struct task_struct *prev,struct task_struct *next) {... ...return cpu_switch_to(prev, next);> .global cpu_switch_tocpu_…...

如何用 HTML 展示计算机代码
原文:如何用 HTML 展示计算机代码 | w3cschool笔记 (请勿将文章标记为付费!!!!) 在编程学习和文档编写过程中,清晰地展示代码是一项关键技能。HTML 作为网页开发的基础语言&#x…...

2025年ESWA SCI1区TOP,自适应学习粒子群算法AEPSO+动态周期调节灰色模型,深度解析+性能实测
目录 1.摘要2.粒子群算法PSO原理3.改进策略4.结果展示5.参考文献6.代码获取7.算法辅导应用定制读者交流 1.摘要 能源数据的科学预测对于能源行业决策和国家经济发展具有重要意义,尤其是短期能源预测,其精度直接影响经济运行效率。为了更好地提高预测模型…...

LeetCode - 53. 最大子数组和
目录 题目 Kadane 算法核心思想 Kadane 算法的步骤分析 读者可能的错误写法 正确的写法 题目 53. 最大子数组和 - 力扣(LeetCode) Kadane 算法核心思想 定义状态变量: currentSum: 表示以当前元素为结束的子数组的最大和。 maxSum: 记录全局最大…...
稻米分类和病害检测数据集(猫脸码客第237期)
稻米分类图像数据集:驱动农业智能化发展的核心资源 引言 在全球农业体系中,稻米作为最关键的粮食作物之一,其品种多样性为人类饮食提供了丰富选择。然而,传统稻米分类方法高度依赖人工经验,存在效率低、主观性强等缺…...
DOM(文档对象模型)深度解析
DOM(文档对象模型)深度解析 DOM 是 HTML/XML 文档的树形结构表示,提供了一套让 JavaScript 动态操作网页内容、结构和样式的接口。 一、DOM 核心概念 1. 节点(Node)类型 类型值说明示例ELEMENT_NODE1元素节点<div>, <p>TEXT_NODE3文本节点元素内的文字COMMEN…...
四、Sqoop 导入表数据子集
作者:IvanCodes 日期:2025年6月4日 专栏:Sqoop教程 当不需要将关系型数据库中的整个表一次性导入,而是只需要表中的一部分数据时,Sqoop 提供了多种方式来实现数据子集的导入。这通常通过过滤条件或选择特定列来完成。 …...

【读代码】从预训练到后训练:解锁语言模型推理潜能——Xiaomi MiMo项目深度解析
项目开源地址:https://github.com/XiaomiMiMo/MiMo 一、基本介绍 Xiaomi MiMo是小米公司开源的7B参数规模语言模型系列,专为复杂推理任务设计。项目包含基础模型(MiMo-7B-Base)、监督微调模型(MiMo-7B-SFT)和强化学习模型(MiMo-7B-RL)等多个版本。其核心创新在于通过…...

DROPP算法详解:专为时间序列和空间数据优化的PCA降维方案
DROPP (Dimensionality Reduction for Ordered Points via PCA) 是一种专门针对有序数据的降维方法。本文将详细介绍该算法的理论基础、实现步骤以及在降维任务中的具体应用。 在现代数据分析中,高维数据集普遍存在特征数量庞大的问题。这种高维特性不仅增加了计算…...
DeepSeek11-Ollama + Open WebUI 搭建本地 RAG 知识库全流程指南
🛠️ Ollama Open WebUI 搭建本地 RAG 知识库全流程指南 💻 一、环境准备 # 1. 安装 Docker 和 Docker Compose sudo apt update && sudo apt install docker.io docker-compose -y# 2. 添加用户到 docker 组(避免 sudo 权限&…...
【AI大模型】Transformer架构到底是什么?
引言 —— 想象一台能瞬间读懂整本《战争与和平》、精准翻译俳句中的禅意、甚至为你的设计草图生成前端代码的机器——这一切并非科幻,而是过去七年AI领域最震撼的技术革命:Transformer架构创造的奇迹。 当谷歌在2017年揭开Transformer的神秘面纱时&…...
code-server安装使用,并配置frp反射域名访问
为什么使用 code-server是VSCode网页版开发软件,可以在浏览器访问编程,可以使用vscode中的插件。如果有自己的服务器,使用frp透传后,域名访问在线编程,使用方便,打开的服务端口不需要单独配置,可…...

MTK-Android12-13 Camera2 设置默认视频画质功能实现
MTK-Android12-13 Camera2 设置默认视频画质功能实现 场景:部分客户使用自己的mipi相机安装到我们主板上,最大分辨率为1280720,但是视频画质默认的是640480。实际场景中,在默认视频分辨率情况下拍出来的视频比较模糊、预览也不清晰…...
Kafka 消息模式实战:从简单队列到流处理(一)
一、Kafka 简介 ** Kafka 是一种分布式的、基于发布 / 订阅的消息系统,由 LinkedIn 公司开发,并于 2011 年开源,后来成为 Apache 基金会的顶级项目。它最初的设计目标是处理 LinkedIn 公司的海量数据,如用户活动跟踪、消息传递和…...

Linux知识回顾总结----进程状态
本章将会介绍进程的一些概念:冯诺伊曼体系结构、进程是什么,怎么用、怎么表现得、进程空间地址、物理地址、虚拟地址、为什么存在进程空间地址、如何感性得去理解进程空间地址、环境变量是如何使用的。 目录 1. 冯诺伊曼体系结构 1.1 是什么 1.2 结论 …...

Linux 进程管理学习指南:架构、计划与关键问题全解
Linux 进程管理学习指南:架构、计划与关键问题全解 本文面向初学者,旨在帮助你从架构视角理解 Linux 进程管理子系统,构建系统化学习路径,并通过结构化笔记方法与典型问题总结,夯实基础、明确方向,逐步掌握…...
【异常】极端事件的概率衰减方式(指数幂律衰减)
在日常事件中,极端事件的概率衰减方式并非单一模式,而是取决于具体情境和数据生成机制。以下是科学依据和不同衰减形式的分析: 1. 指数衰减(Exponential Decay) 典型场景:当事件服从高斯分布(正态分布)或指数分布时,极端事件的概率呈指数衰减。 数学形式:概率密度函数…...

Git 使用大全:从入门到精通
Git 是目前最流行的分布式版本控制系统,被广泛应用于软件开发中。本文将全面介绍 Git 的各种功能和使用方法,包含大量代码示例和实践建议。 文章目录 Git 基础概念版本控制系统Git 的特点Git 的三个区域Git 文件状态 Git 安装与配置安装 GitLinuxmacOSWi…...

奈飞工厂官网,国内Netflix影视在线看|中文网页电脑版入口
奈飞工厂是一个专注于提供免费Netflix影视资源的在线播放平台,致力于为国内用户提供的Netflix热门影视内容。该平台的资源与Netflix官网基本同步,涵盖电影、电视剧、动漫和综艺等多个领域。奈飞工厂的界面简洁流畅,资源分类清晰,方…...

Python基于蒙特卡罗方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融投资中,风险管理是确保资产安全和实现稳健收益的关键环节。随着市场波动性的增加,传统…...
【bat win系统自动运行脚本-双击启动docker及其它】
win系统自动化运行脚本 创建一个 startup.bat右键编辑,输入以下示例 echo off start "" "C:\Program Files\Docker\Docker\Docker Desktop.exe"timeout /t 5docker start your_container_namestart cmd /k "conda activate your_conda_e…...
SpringBoot离线应用的5种实现方式
在当今高度依赖网络的环境中,离线应用的价值日益凸显。无论是在网络不稳定的区域运行的现场系统,还是需要在断网环境下使用的企业内部应用,具备离线工作能力已成为许多应用的必备特性。 本文将介绍基于SpringBoot实现离线应用的5种不同方式。…...
js 比较两个对象的值,不相等就push对象的key
在JavaScript中,比较两个对象(object)的值并找出不相等的key,可以通过多种方法实现。下面是一些常用的方法: 方法1:使用JSON.stringify 这种方法适用于简单的对象,其中对象的值是基本类型或可…...
SQL 注入开放与修复
开发: SQL 注入是一种数据库攻击手段。攻击者通过向应用程序提交恶意代码来改变原 SQL 语句的含义, 进而执行任意 SQL 命令,达到入侵数据库乃至操作系统的目的。 例如:下面代码片段中,动态构造并执行了一个 SQ…...

【学习记录】Office 和 WPS 文档密码破解实战
文章目录 📌 引言📁 Office 与 WPS 支持的常见文件格式Microsoft Office 格式WPS Office 格式 🛠 所需工具下载地址(Windows 官方编译版)🔐 破解流程详解步骤 1:提取文档的加密哈希值步骤 2&…...

AGV|无人叉车工业语音播报器|预警提示器LBE-LEX系列性能与接线说明
LBE-LEX系列AGV|无人叉车工业语音播报器|预警提示器,涵盖LBE-LEI-M-00、LBE-LESM-00、LBE-LES-M-01、LBE-LEC-M-00、LBE-KEI-M-00、LBE-KES-M-00、LBE-KES-M-01、LBE-KEC-M-00等型号,适用于各种需要语音提示的场景,主要有AGV、AMR机器人、无人…...