前端技术
HTML
CSS
Javascript
前端框架和UI库
VUE
ReactJS
AngularJS
JQuery
NodeJS
JSON
Element-UI
Bootstrap
Material UI
服务端和客户端
Java
Python
PHP
Golang
Scala
Kotlin
Groovy
Ruby
Lua
.net
c#
c++
后端WEB和工程框架
SpringBoot
SpringCloud
Struts2
MyBatis
Hibernate
Tornado
Beego
Go-Spring
Go Gin
Go Iris
Dubbo
HessianRPC
Maven
Gradle
数据库
MySQL
Oracle
Mongo
中间件与web容器
Redis
MemCache
Etcd
Cassandra
Kafka
RabbitMQ
RocketMQ
ActiveMQ
Nacos
Consul
Tomcat
Nginx
Netty
大数据技术
Hive
Impala
ClickHouse
DorisDB
Greenplum
PostgreSQL
HBase
Kylin
Hadoop
Apache Pig
ZooKeeper
SeaTunnel
Sqoop
Datax
Flink
Spark
Mahout
数据搜索与日志
ElasticSearch
Apache Lucene
Apache Solr
Kibana
Logstash
数据可视化与OLAP
Apache Atlas
Superset
Saiku
Tesseract
系统与容器
Linux
Shell
Docker
Kubernetes
[客户端JavaScript]的搜索结果
这里是文章列表。热门标签的颜色随机变换,标签颜色没有特殊含义。
点击某个标签可搜索标签相关的文章。
点击某个标签可搜索标签相关的文章。
转载文章
...一般分为服务段开发与客户端开发,方向不同,接下去学的知识点就会不同。所以这里选择需要慎重思考。 这里可以使用一个方法,我们从事件的价值出发,列出一个优缺清单表。比如你要选择服务端开发还是客户端开发,你先去充分了解这两个方向,然后列一分优缺清单表格,把了解到每一个点都写上去,打一个分数,分数分为 -10 到 10 分。最后我们统计一个总分,然后那个分数较高的方向。 掌握数据库 由于本人从事服务端开发,下面说说服务端开发学习的过程。 服务端开发,需要学习的东西会很多,不过不用担心,我们一个个说。 首先我们先说数据库。数据库对于服务端开发,一定要学会的技术,所以这个我们需要着重学习。 首先按照网上教程,自己在电脑上搭建一个数据库,这里推荐 MySQL。搭建之后,再下载一个数据库客户端管理工具,如 Navicat,DataGrip。弄完这些基础设施之后,我们这里接着去学会 SQL 的语法。这里着重学习单表增删改查的语法,跨表的连接查询等。网上找一个例子,如可以自己构建一个学生课程信息表,做到可以用以上学习到的语法。 学习完数据库,接着我们就需要学习Java JDBC 的知识。学习的 JDBC 就是让我们了解,如何使用 Java 操作数据库,运行 Mybatis的增删改查的语句。 接着我们可以去学习相关 ORM 的框架,如 Hibernate 或 Mybatis,这里推荐 Mybatis。学习框架,我们要做到掌握框架的使用技巧就可以。 这个过程你可能会发现,Mybatis 这类框架这么如此简化开发,为什么我们不直接学习 Mybatis ? 学习 JDBC 的目的,其实就是让你了解这些 ORM 的基础。 学完这个阶段,我们接下去就要进入 WEB 开发。 WEB 开发 这个过程我们首先学习一些前端知识,如 HTML,CSS,JavaScript,然后再去 Jquery 等前端框架,做到能实现一些简单的功能。我们不需要跟你上面一样精通,我们只要了解一些概念即可。 接下去我们学习 Servlet,做到能使用原生 Servlet + Jsp 能运行一个 WEB 程序。 后面我们再去学习 Spring 框架,使用 SpringMVC 了解 MVC 的概念。最后用 SpringMVC+Spring+Mybatis+MySQL 完成一个简单的管理系统。 其他 学完以上内容,基本上已经学习完工作中学习到的技术栈。这个过程你还需要额外学习一些工作中用到其他知识。 你需要去学习协同开发的工具,如 Git,SVN。做到了解如何新建分支,如何拉取代码,如何合并代码即可。 你还需要去学习一些 Linux 的命令。 总结 学完上述内容,你实际就已经掌握初级开发所需要的技术,已经基本上可以从事一个初级开发的岗位。我们上面讲的都是使用技巧,但是面试的时候可能会问你一些原理性的内容,所以在我们去找工作之前我们还需要去了解一些原理性知识。这方面的内容通过搜索引擎搜索即可。 这个过程你可能会碰到很多问题,这个过程一定善于使用搜索引擎。 本篇文章为转载内容。原文链接:https://blog.csdn.net/qq_35006660/article/details/115610534。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-07-02 23:59:06
60
转载
Go Gin
...径/ping,当客户端访问这个地址时,会返回JSON格式的数据{"message": "pong"}。 个人感悟 刚接触这段代码的时候,我有点被惊到了——这么少的代码竟然能完成如此多的功能!当然,这也得益于Gin的设计理念:尽可能简化开发流程,让程序员专注于业务逻辑而不是框架细节。 --- 三、实时处理的核心 WebSocket支持 既然我们要讨论实时处理,那么就不得不提WebSocket。WebSocket就像是一个永不掉线的“聊天热线”,能让浏览器和服务器一直保持着畅通的联系。跟传统的请求-响应模式不一样,它可以让双方随时自由地“唠嗑”,想发啥就发啥,特别适合那些需要实时互动的应用,比如聊天室里你一言我一语,或者股票行情那种分分钟都在变化的东西,用它简直太合适了! Gin内置了对WebSocket的支持,我们可以直接通过中间件来实现这一功能。下面是一个完整的WebSocket示例: go package main import ( "log" "net/http" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" ) var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r http.Request) bool { return true // 允许跨域 }, } func handleWebSocket(c gin.Context) { ws, err := upgrader.Upgrade(c.Writer, c.Request, nil) if err != nil { log.Println("Failed to upgrade:", err) return } defer ws.Close() for { messageType, msg, err := ws.ReadMessage() if err != nil { log.Println("Error reading message:", err) break } log.Printf("Received: %s\n", string(msg)) err = ws.WriteMessage(messageType, msg) if err != nil { log.Println("Error writing message:", err) break } } } func main() { r := gin.Default() r.GET("/ws", handleWebSocket) r.Run(":8080") } 在这段代码中,我们利用gorilla/websocket包实现了WebSocket升级,并在handleWebSocket函数中处理了消息的读取与发送。你可以试着在浏览器里输入这个地址:ws://localhost:8080/ws,然后用JavaScript发个消息试试,看能不能马上收到服务器的回应。 深入探讨 说实话,刚开始写这部分代码的时候,我还担心WebSocket的兼容性问题。后来发现,只要正确设置了CheckOrigin方法,大多数现代浏览器都能正常工作。这让我更加坚定了对Gin的信心——它虽然简单,但足够强大! --- 四、进阶技巧 并发与性能优化 在实际项目中,我们可能会遇到高并发的情况。为了保证系统的稳定性,我们需要合理地管理线程池和内存分配。Gin提供了一些工具可以帮助我们做到这一点。 例如,我们可以使用sync.Pool来复用对象,减少垃圾回收的压力。下面是一个示例: go package main import ( "sync" "time" "github.com/gin-gonic/gin" ) var pool sync.Pool func init() { pool = &sync.Pool{ New: func() interface{} { return make([]byte, 1024) }, } } func handler(c gin.Context) { data := pool.Get().([]byte) defer pool.Put(data) copy(data, []byte("Hello World!")) time.Sleep(100 time.Millisecond) // 模拟耗时操作 c.String(http.StatusOK, string(data)) } func main() { r := gin.Default() r.GET("/", handler) r.Run(":8080") } 在这个例子中,我们定义了一个sync.Pool来存储临时数据。每次处理请求时,从池中获取缓冲区,处理完毕后再放回池中。这样可以避免频繁的内存分配和释放,从而提升性能。 反思与总结 其实,刚开始学习这段代码的时候,我对sync.Pool的理解还停留在表面。直到后来真正用它解决了性能瓶颈,我才意识到它的价值所在。这也让我明白,优秀的框架只是起点,关键还是要结合实际需求去探索和实践。 --- 五、未来展望 Gin与实时处理的无限可能 Gin的强大之处不仅仅在于它的易用性和灵活性,更在于它为开发者提供了广阔的想象空间。无论是构建大型分布式系统,还是打造小型实验项目,Gin都能胜任。 如果你也想尝试用Gin构建实时处理系统,不妨从一个小目标开始——比如做一个简单的在线聊天室。相信我,当你第一次看到用户实时交流的画面时,那种成就感绝对会让你欲罢不能! 最后的话 写这篇文章的过程,其实也是我自己重新审视Gin的过程。其实这个东西吧,说白了挺简单的,但让我学到了一个本事——用最利索的办法搞定事情。希望能这篇文章也能点醒你,让你在今后的开发路上,慢慢琢磨出属于自己的那套玩法!加油吧,程序员们!
2025-04-07 16:03:11
65
时光倒流
转载文章
... 一个开源、跨平台的JavaScript运行环境,允许开发者使用JavaScript编写服务器端代码,实现高性能、可伸缩的网络应用。文中提到安装Node.js,并配置淘宝源以优化npm包下载速度,为开发基于Node.js的后端服务或者全栈Web应用提供了基础条件。 Nginx , 一款高性能的HTTP和反向代理服务器,同时也可用作邮件代理服务器和负载均衡器。在该文场景下,Nginx被用作Web服务器,负责处理和分发来自客户端的HTTP请求,对于部署静态网站或作为Web应用的前端服务器非常适用。 PostgreSQL , 一种开源的关系型数据库管理系统,支持丰富的SQL标准和高级特性,如窗口函数、多版本并发控制等。在文中安装PostgreSQL是为了解决项目中的持久化存储需求,用于存放应用的数据。 Redis , 一个开源的、内存中的数据结构存储系统,常被用作数据库、缓存和消息中间件。在该篇文章里,Redis被安装和配置,用来提高应用的数据读写性能,尤其是在高并发场景下提供快速响应的能力。
2023-11-15 19:14:44
54
转载
NodeJS
...双工通信协议,可以让客户端和服务端随时互相推送消息,简直是实时应用的最佳拍档! 说到 Node.js,它天生就擅长处理异步事件流,再加上强大的生态系统(比如 Express、Socket.IO 等),简直就是为实时应用量身定制的工具。所以,今天我们就用 Node.js + WebSocket 来做一个简单的实时监控面板,顺便分享一下我的一些心得。 --- 2. 第一步 搭建基础环境 首先,我们需要准备开发环境。Node.js 的安装非常简单,去官网下载对应版本就行。安装完后,用 node -v 和 npm -v 验证是否成功。如果这两个命令都能正常输出版本号,那就说明环境配置好了。 接下来,我们创建项目文件夹,并初始化 npm: bash mkdir real-time-monitor cd real-time-monitor npm init -y 然后安装必要的依赖包。这里我们用到两个核心库:Express 和 ws(WebSocket 库)。Express 是用来搭建 HTTP 服务的,ws 则专门用于 WebSocket 通信。 bash npm install express ws 接下来,我们写一个最基础的 HTTP 服务,确保环境能正常工作: javascript // server.js const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Hello World!'); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(Server is running on port ${PORT}); }); 保存文件后运行 node server.js,然后在浏览器输入 http://localhost:3000,应该能看到 “Hello World!”。到这里,我们的基本框架已经搭好了,是不是感觉还挺容易的? --- 3. 第二步 引入 WebSocket 现在我们有了一个 HTTP 服务,接下来该让 WebSocket 上场了。WebSocket 的好处就是能在浏览器和服务器之间直接搭起一条“高速公路”,不用老是像发短信那样频繁地丢 HTTP 请求过去,省时又高效!为了方便,我们可以直接用 ws 库来实现。 修改 server.js 文件,添加 WebSocket 相关代码: javascript // server.js const express = require('express'); const WebSocket = require('ws'); const app = express(); const wss = new WebSocket.Server({ port: 8080 }); wss.on('connection', (ws) => { console.log('A client connected!'); // 接收来自客户端的消息 ws.on('message', (message) => { console.log(Received message => ${message}); ws.send(You said: ${message}); }); // 当客户端断开时触发 ws.on('close', () => { console.log('Client disconnected.'); }); }); app.get('/', (req, res) => { res.sendFile(__dirname + '/index.html'); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(HTTP Server is running on port ${PORT}); }); 这段代码做了几件事: 1. 创建了一个 WebSocket 服务器,监听端口 8080。 2. 当客户端连接时,打印日志并等待消息。 3. 收到消息后,会回传给客户端。 4. 如果客户端断开连接,也会记录日志。 为了让浏览器能连接到 WebSocket 服务器,我们还需要一个简单的 HTML 页面作为客户端入口: html Real-Time Monitor WebSocket Test Send Message 这段 HTML 代码包含了一个简单的聊天界面,用户可以在输入框中输入内容并通过 WebSocket 发送到服务器,同时也能接收到服务器返回的信息。跑完 node server.js 之后,别忘了打开浏览器,去 http://localhost:3000 看一眼,看看它是不是能正常转起来。 --- 4. 第三步 扩展功能——实时监控数据 现在我们的 WebSocket 已经可以正常工作了,但还不能算是一个真正的监控面板。为了让它更实用一点,咱们不妨假装弄点监控数据玩玩,像CPU用得多不多、内存占了百分之多少之类的。 首先,我们需要一个生成随机监控数据的函数: javascript function generateRandomMetrics() { return { cpuUsage: Math.random() 100, memoryUsage: Math.random() 100, diskUsage: Math.random() 100 }; } 然后,在 WebSocket 连接中定时向客户端推送这些数据: javascript wss.on('connection', (ws) => { console.log('A client connected!'); setInterval(() => { const metrics = generateRandomMetrics(); ws.send(JSON.stringify(metrics)); }, 1000); // 每秒发送一次 ws.on('close', () => { console.log('Client disconnected.'); }); }); 客户端需要解析接收到的数据,并动态更新页面上的信息。我们可以稍微改造一下 HTML 和 JavaScript: html CPU Usage: Memory Usage: Disk Usage: javascript socket.onmessage = (event) => { const metrics = JSON.parse(event.data); document.getElementById('cpuProgress').value = metrics.cpuUsage; document.getElementById('memoryProgress').value = metrics.memoryUsage; document.getElementById('diskProgress').value = metrics.diskUsage; const messagesDiv = document.getElementById('messages'); messagesDiv.innerHTML += Metrics updated. ; }; 这样,每秒钟都会从服务器获取一次监控数据,并在页面上以进度条的形式展示出来。是不是很酷? --- 5. 结尾 总结与展望 通过这篇文章,我们从零开始搭建了一个基于 Node.js 和 WebSocket 的实时监控面板。别看它现在功能挺朴素的,但这东西一出手就让人觉得,WebSocket 在实时互动这块儿真的大有可为啊!嘿,听我说!以后啊,你完全可以接着把这个项目捯饬得更酷一些。比如说,弄点新鲜玩意儿当监控指标,让用户用起来更爽,或者直接把它整到真正的生产环境里去,让它发挥大作用! 其实开发的过程就像拼图一样,有时候你会遇到困难,但只要一点点尝试和调整,总会找到答案。希望这篇文章能给你带来灵感,也欢迎你在评论区分享你的想法和经验! 最后,如果你觉得这篇文章对你有帮助,记得点个赞哦!😄 --- 完
2025-05-06 16:24:48
71
清风徐来
转载文章
...ype="text/javascript">function getprofenlei(){ var html = ""; $.ajax({url: "leixing.action?list&page=0&rows=30",type: "POST",async: false, contentType: "application/x-www-form-urlencoded;charset=UTF-8",success: function (data) { $.each(data.rows, function (i, val) { html += ' <li ><a href="home/search.jsp?fenlei='+val.id+'" >'+val.a1+' </a></li>';})} }); $("fenlei").html(html);}function gettop1(){var html = "";$.ajax({url: "leixing.action?list&page=0&rows=10",type: "POST",async: false,success: function (data) {var total='';//<div class="tab-pane active" id="nArrivals">// <div class="nArrivals owl-carousel" id="top1">$.each(data.rows, function (i, valmm) { html+='<div class="nArrivals owl-carousel" id="'+valmm.id+'">';$.ajax({url: "shangpin.action?list&page=0&rows=10",type: "POST",async: false,data: { fenlei:valmm.id },success: function (data) { $.each(data.rows, function (i, val) { html+='<div class="product-grid">'+'<div class="item">'+' <div class="product-thumb">'+' <div class="image product-imageblock"> <a href="home/details.jsp?ids='+val.id+'"> <img data-name="product_image" style="width:223px;height:285px;" src="<%=basePath%>'+val.tupian1+'" alt="iPod Classic" title="iPod Classic" class="img-responsive"> <img style="width:223px;height:285px;" src="<%=basePath%>'+val.tupian1+'" alt="iPod Classic" title="iPod Classic" class="img-responsive"> </a> </div>'+' <div class="caption product-detail text-left">'+' <h6 data-name="product_name" class="product-name mt_20"><a href="home/details.jsp?ids='+val.id+'" title="Casual Shirt With Ruffle Hem">'+val.biaoti+'</a></h6>'+' <div class="rating"> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-1x"></i></span> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-1x"></i></span> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-1x"></i></span> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-1x"></i></span> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-x"></i></span> </div>'+'<span class="price"><span class="amount"><span class="currencySymbol">$</span>'+val.jiage+'</span>'+'</span>'+'<div class="button-group text-center">'+' <div class="wishlist"><a href="home/details.jsp?ids='+val.id+'"><span>wishlist</span></a></div>'+'<div class="quickview"><a href="home/details.jsp?ids='+val.id+'"><span>Quick View</span></a></div>'+'<div class="compare"><a href="home/details.jsp?ids='+val.id+'"><span>Compare</span></a></div>'+'<div class="add-to-cart"><a href="home/details.jsp?ids='+val.id+'"><span>Add to cart</span></a></div>'+'</div>'+'</div>'+'</div>'+'</div>'+' </div>'; })html+='</div>'; } })}) $("nArrivals").html(html); } }); 本篇文章为转载内容。原文链接:https://blog.csdn.net/newlw/article/details/127608579。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-03-21 18:24:50
66
转载
转载文章
... //如果成功提交 javascript:$.fancybox.close(); $("uploadUserHead").hide(); var data = msg.object; $("editImg").attr("src", data.path).show(); $("preview1").attr("src", data.path).show(); $(".zoom").show(); $("width").val(data.width); $("height").val(data.height); $("oldImgPath").val(data.realPath); $("imgFileExt").val(data.fileExt); var api, jcrop_api, boundx, boundy; $('editImg').Jcrop({ onChange:updatePreview, onSelect:updatePreview, aspectRatio:1, bgOpacity:0.5, bgColor:'white', addClass:'jcrop-light' }, function () { api = this; api.setSelect([130, 65, 130 + 350, 65 + 285]); api.setOptions({ bgFade:true }); api.ui.selection.addClass('jcrop-selection'); var bounds = this.getBounds(); boundx = bounds[0]; boundy = bounds[1]; jcrop_api = this; }); function updatePreview(c) { if (parseInt(c.w) > 0) { var rx = 80 / c.w; var ry = 80 / c.h; $('preview1').css({ width:Math.round(rx boundx) + 'px', height:Math.round(ry boundy) + 'px', marginLeft:'-' + Math.round(rx c.x) + 'px', marginTop:'-' + Math.round(ry c.y) + 'px' }); } jQuery('x').val(c.x); jQuery('y').val(c.y); jQuery('x2').val(c.x2); jQuery('y2').val(c.y2); jQuery('w').val(c.w); jQuery('h').val(c.h); } } if (msg.code == 204) { $("uploadMsg").html(msg.msg); } }catch (e){ $("uploadMsg").html('上传文件超过1M!'); } } }); }); //服务器端处理代码 String tempSavePath = ConfigurationUtils.get("user.resource.dir"); //上传的图片零时保存路径 String tempShowPath = ConfigurationUtils.get("user.resource.url"); //用户保存的头像路径 if(tempSavePath.equals("/img")) { tempSavePath=sc.getRealPath("/")+tempSavePath; } Msg msg = new Msg(); msg.setCode(204); msg.setMsg("上传头像失败!"); String type = request.getParameter("type"); if (!Strings.isNullOrEmpty(type) && type.equals("first")) { request.setCharacterEncoding("utf-8"); DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload servletFileUpload = new ServletFileUpload(factory); try { List items = servletFileUpload.parseRequest(request); Iterator iterator = items.iterator(); while (iterator.hasNext()) { FileItem item = (FileItem) iterator.next(); if (!item.isFormField()) { { File tempFile = new File(item.getName()); File saveTemp = new File(tempSavePath+"/tempImg/"); String getItemName=tempFile.getName(); String fileName = UUID.randomUUID()+"." +getItemName.substring(getItemName.lastIndexOf(".") + 1, getItemName.length()); File saveDir = new File(tempSavePath+"/tempImg/", fileName); //如果目录不存在,创建。 if (saveTemp.exists() == false) { if (!saveTemp.mkdir()) { // 创建失败 saveTemp.getParentFile().mkdir(); saveTemp.mkdir(); } else { } } if (saveDir.exists()) { log.info("存在同名文件···"); saveDir.delete(); } item.write(saveDir); log.info("上传头像成功!"+saveDir.getName()); msg.setCode(200); msg.setMsg("上传头像成功!"); Image image = new Image(); BufferedImage bufferedImage = null; try { bufferedImage = ImageIO.read(saveDir); } catch (IOException e) { e.printStackTrace(); } image.setHeight(bufferedImage.getHeight()); image.setWidth(bufferedImage.getWidth()); image.setPath(tempShowPath+ "/tempImg/" + fileName); log.info(image.getPath()); image.setRealPath(tempSavePath+"/tempImg/"+ fileName); image.setFileExt(fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length())); msg.setObject(image); } } else { log.info("" + item.getFieldName()); } } } catch (Exception ex) { log.error("上传用户头像图片异常!"); ex.printStackTrace(); } finally { AppHelper.returnJsonAjaxForm(response, msg); } } 上传成功后,可以看到照片和照片的预览效果。看图: 上传头像之后的效果 Friday, October 05, 2012 第二步:编辑和保存头像 选中图中的区域,保存头像,就完成头像的修改。 修改之后的效果入下: 修改之后的头像(因为传了一张动态图片,得到的跟上图有些不同) 实现细节: 首先用了一个js控件:Jcrop,有兴趣的屌丝可以去搜一下,然后,利用上传之后的图片和之前的选定区域,完成了一个截图,保存为用户的头像。 连接层的js: $("saveHead").bind("click", function () { var width = $("width").val(); var height = $("height").val(); var oldImgPath = $("oldImgPath").val(); var imgFileExt = $("imgFileExt").val(); var x = $('x').val(); var y = $('y').val(); var w = $('w').val(); var h = $('h').val(); $.ajax({ url:'/imgCrop', type:'post', data:{x:x, y:y, w:w, h:h, width:width, height:height, oldImgPath:oldImgPath, fileExt:imgFileExt}, datatype:'json', success:function (msg) { if (msg.code == 200) { $("avatar").attr("src", msg.object); forword('/nav', 'index'); } else { alert(msg.msg); } } }); }); function checkImg() { //限制上传文件的大小和后缀名 var filePath = $("input[name='uploadImg']").val(); if (!filePath) { $("uploadMsg").html("请选择上传文件!").show(); return false; } else { var extStart = filePath.lastIndexOf("."); var ext = filePath.substring(extStart, filePath.length).toUpperCase(); if (ext != ".PNG" && ext != ".GIF" && ext != ".JPG") { $("uploadMsg").html("图片限于png,gif,jpg格式!").show(); return false; } } return true; } 服务器端处理代码: String savePath = ConfigurationUtils.get("user.resource.dir"); //上传的图片保存路径 String showPath = ConfigurationUtils.get("user.resource.url"); //显示图片的路径 if(savePath.equals("/img")) { savePath=sc.getRealPath("/")+savePath; } int userId = AppHelper.getUserId(request); String userName=AppHelper.getUserName(request); Msg msg = new Msg(); msg.setCode(204); msg.setMsg("剪切图片失败!"); if (userId <= 0) { msg.setMsg("请先登录"); return; } // 用户经过剪辑后的图片的大小 Integer x = (int)Float.parseFloat(request.getParameter("x")); Integer y = (int)Float.parseFloat(request.getParameter("y")); Integer w = (int)Float.parseFloat(request.getParameter("w")); Integer h = (int)Float.parseFloat(request.getParameter("h")); //获取原显示图片路径 和大小 String oldImgPath = request.getParameter("oldImgPath"); Integer width = (int)Float.parseFloat(request.getParameter("width")); Integer height = (int)Float.parseFloat(request.getParameter("height")); //图片后缀 String imgFileExt = request.getParameter("fileExt"); String foldName="/"+ DateUtils.nowDatetoStrToMonth()+"/"; String imgName = foldName + UUID.randomUUID()+userName + "." + imgFileExt; //组装图片真实名称 String createImgPath = savePath + imgName; //进行剪切图片操作 ImageCut.abscut(oldImgPath,createImgPath, xwidth/300, yheight/300, wwidth/300, hheight/300); File f = new File(createImgPath); if (f.exists()) { msg.setObject(imgName); //把显示路径保存到用户信息下面。 UserService userService = userServiceProvider.get(); int rel = userService.updateUserAvatar(userId, showPath+imgName); if (rel >= 1) { msg.setCode(200); msg.setMsg("剪切图片成功!"); log.info("剪切图片成功!"); //记录日志,更新session log(showPath+imgName,userName); UserObject userObject= userService.getUserObject(userName); request.getSession().setAttribute("userObject", userObject); if (userObject != null && Strings.isNullOrEmpty(userObject.getHeadDir())) userObject.setHeadDir("/images/geren_right_01.jpg"); } else { msg.setCode(204); msg.setMsg("剪切图片失败!"); log.info("剪切图片失败!"); } } AppHelper.returnJson(response, msg); File file=new File(oldImgPath); boolean deleteFile= file.delete(); if(deleteFile==true) { log.info("删除原来图片成功"); } / 图像切割(改) @param srcImageFile 源图像地址 @param dirImageFile 新图像地址 @param x 目标切片起点x坐标 @param y 目标切片起点y坐标 @param destWidth 目标切片宽度 @param destHeight 目标切片高度 / public static void abscut(String srcImageFile, String dirImageFile, int x, int y, int destWidth, int destHeight) { try { Image img; ImageFilter cropFilter; // 读取源图像 BufferedImage bi = ImageIO.read(new File(srcImageFile)); int srcWidth = bi.getWidth(); // 源图宽度 int srcHeight = bi.getHeight(); // 源图高度 if (srcWidth >= destWidth && srcHeight >= destHeight) { Image image = bi.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT); // 改进的想法:是否可用多线程加快切割速度 // 四个参数分别为图像起点坐标和宽高 // 即: CropImageFilter(int x,int y,int width,int height) cropFilter = new CropImageFilter(x, y, destWidth, destHeight); img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter)); BufferedImage tag = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB); Graphics g = tag.getGraphics(); g.drawImage(img, 0, 0, null); // 绘制缩小后的图 g.dispose(); // 输出为文件 ImageIO.write(tag, "JPEG", new File(dirImageFile)); } } catch (Exception e) { e.printStackTrace(); } } 最后一个处理的比较好的地方就是图片的存储路径问题: 我在服务器端的nginx中做了一个图片的地址映射,把图片放到了跟程序不同的路径中,每次存储图片都是存到图片路径中,客户端拿到图片的地址确实经过nginx映射过的地址。 还有就是关于限制上传图片的大小的问题: 我在服务器端显示了资源的最大大小为1M,当上传的资源超过1M,服务器自动报错413,通过异常处理,可以在客户端得到正确的提示信息。 4,总结优点和不足。 关于修改头像,这么做下来确实达到了目的,用户可以从容的修改头像,性能也还可以。但是,上传图片的大小判断是依靠服务器端来判断的,等待的时间比较久,改进的方向是使用flash控件来限制,使用flash来上传,也不会出现弹出层,这样比较大众化,更容易为用户接受一点。我会不断改进。 本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_39849287/article/details/111489534。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-07-18 10:58:17
268
转载
转载文章
...服务器进一步处理前,JavaScript 程序会检查表单以确认用户确实输入了信息并且这些信息是符合要求的。 什么是正则表达式 正则表达式(regular expression)是一个描述字符模式的对象。ECMAScript 的 RegExp 类表示正则表达式,而 String 和 RegExp 都定义了使用正则表达式进行强大的模式匹配和文本检索与替换的函数。 正则表达式主要用来验证客户端的输入数据。用户填写完表单单击按钮之后,表单就会被发送到服务器,在服务器端通常会用 PHP、ASP.NET 等服务器脚本对其进行进一步处理 。因为客户端验证,可以节约大量的服务器端的系统资源,并且提供更好的用户体验。 创建正则表达式 创建正则表达式和创建字符串类似,创建正则表达式提供了两种方法,一种是采用 new 运算符,另一个是采用字面量方式。 两种创建方式 var box = new RegExp('box'); // 第一个参数字符串var box = new RegExp('box', 'ig'); // 第二个参数可选模式修饰符 模式修饰符的可选参数 参数 含义 i 忽略大小写 g 全局匹配 m 多行匹配 var box = /box/; // 直接用两个反斜杠var box = /box/ig; // 在第二个斜杠后面加上模式修饰符 测试正则表达式 RegExp 对象包含两个方法:test()和 exec(),功能基本相似,用于测试字符串匹配。test()方法在字符串中查找是否存在指定的正则表达式并返回布尔值,如果存在则返回 true,不存在则返回 false。exec()方法也用于在字符串中查找指定正则表达式,如果 exec()方法执行成功,则返回包含该查找字符串的相关信息数组。如果执行失败,则返回 null。 RegExp 对象的方法 方法 功能 test 在字符串中测试模式匹配,返回 true 或 false exec 在字符串中执行匹配搜索,返回结果数组 // 使用 new 运算符的 test 方法示例var pattern = new RegExp('box', 'i'); // 创建正则模式,不区分大小写var str = 'This is a Box!'; // 创建要比对的字符串alert(pattern.test(str)); // 通过 test()方法验证是否匹配// 使用字面量方式的 test 方法示例var pattern = /box/i; // 创建正则模式,不区分大小写var str = 'This is a Box!';alert(pattern.test(str));// 使用一条语句实现正则匹配alert(/box/i.test('This is a Box!')); // 模式和字符串替换掉了两个变量// 使用 exec 返回匹配数组var pattern = /box/i;var str = 'This is a Box!';alert(pattern.exec(str)); // 匹配了返回数组,否则返回 null 使用字符串的正则表达式方法 除了 test()和 exec()方法,String 对象也提供了 4 个使用正则表达式的方法。 String 对象中的正则表达式方法 方法 含义 match(pattern) 返回 pattern 中的子串或 null replace(pattern, replacement) 用 replacement 替换 pattern search(pattern) 返回字符串中 pattern 开始位置 split(pattern) 返回字符串按指定 pattern 拆分的数组 // 使用 match 方法获取获取匹配数组var pattern = /box/ig; // 全局搜索var str = 'This is a Box!,That is a Box too';alert(str.match(pattern)); // 匹配到两个 Box,Boxalert(str.match(pattern).length); // 获取数组的长度// 使用 search 来查找匹配数据var pattern = /box/ig;var str = 'This is a Box!,That is a Box too';alert(str.search(pattern)); // 查找到返回位置,否则返回-1 因为 search 方法查找到即返回,也就是说无需 g 全局。 // 使用 replace 替换匹配到的数据var pattern = /box/ig;var str = 'This is a Box!,That is a Box too';alert(str.replace(pattern, 'Tom')); // 将 Box 替换成了 Tom// 使用 split 拆分成字符串数组var pattern = / /ig;var str = 'This is a Box!,That is a Box too';alert(str.split(pattern)); // 将空格拆开分组成数组 RegExp 对象的静态属性 属性 短名 含义 input $_ 当前被匹配的字符串 lastMatch $& 最后一个匹配字符串 lastParen $+ 最后一对圆括号内的匹配子串 leftContext $ 最后一次匹配前的子串 multiline $ 用于指定是否所有的表达式都用于多行的布尔值 rightContext $’ 在上次匹配之后的子串 // 使用静态属性var pattern = /(g)oogle/;var str = 'This is google!';pattern.test(str); // 执行一下alert(RegExp.input); // This is google!alert(RegExp.leftContext); // This isalert(RegExp.rightContext); // !alert(RegExp.lastMatch); // googlealert(RegExp.lastParen); // galert(RegExp.multiline); // false Opera 不支持 input、lastMatch、lastParen 和 multiline 属性。IE 不支持 multiline 属性。所有的属性可以使用短名来操作。RegExp.input 可以改写成 RegExp['$_'],依次类推。但 RegExp.input 比较特殊,它还可以写成 RegExp.$_。 RegExp 对象的实例属性 属性 含义 global Boolean 值,表示 g 是否已设置 ignoreCase Boolean 值,表示 i 是否已设置 lastIndex 整数,代表下次匹配将从哪里字符位置开始 multiline Boolean 值,表示 m 是否已设置 Source 正则表达式的源字符串形式 // 使用实例属性var pattern = /google/ig;alert(pattern.global); // true,是否全局了alert(pattern.ignoreCase); // true,是否忽略大小写alert(pattern.multiline); // false,是否支持换行alert(pattern.lastIndex); // 0,下次的匹配位置alert(pattern.source); // google,正则表达式的源字符串var pattern = /google/g;var str = 'google google google';pattern.test(str); // google,匹配第一次alert(pattern.lastIndex); // 6,第二次匹配的位 以上基本没什么用。并且 lastIndex 在获取下次匹配位置上 IE 和其他浏览器有偏差 ,主要表现在非全局匹配上。lastIndex 还支持手动设置,直接赋值操作。 获取控制 正则表达式元字符是包含特殊含义的字符。它们有一些特殊功能,可以控制匹配模式的方式。反斜杠后的元字符将失去其特殊含义。 字符类:单个字符和数字 元字符/元符号 匹配情况 . 匹配除换行符外的任意字符 [a-z0-9] 匹配括号中的字符集中的任意字符 [^a-z0-9] 匹配任意不在括号中的字符集中的字符 \d 匹配数字 \D 匹配非数字,同[^0-9]相同 \w 匹配字母和数字及_ \W 匹配非字母和数字及_ 字符类:空白字符 元字符/元符号 匹配情况 \0 匹配 null 字符 \b 匹配空格字符 \f 匹配进纸字符 \n 匹配换行符 \r 匹配回车字符 \t 匹配制表符 \s 匹配空白字符、空格、制表符和换行符 \S 匹配非空白字符 字符类:锚字符 元字符/元符号 匹配情况 ^ 行首匹配 $ 行尾匹配 \A 只有匹配字符串开始处 \b 匹配单词边界,词在[]内时无效 \B 匹配非单词边界 \G 匹配当前搜索的开始位置 \Z 匹配字符串结束处或行尾 \z 只匹配字符串结束处 字符类:重复字符 元字符/元符号 匹配情况 x? 匹配 0 个或 1 个 x x 匹配 0 个或任意多个 x x+ 匹配至少一个 x (xyz)+ 匹配至少一个(xyz) x{m,n} 匹配最少 m 个、最多 n 个 x 字符类:替代字符 元字符/元符号 匹配情况 this where 字符类:记录字符 元字符/元符号 匹配情况 (string) 用于反向引用的分组 \1 或$1 匹配第一个分组中的内容 \2 或$2 匹配第二个分组中的内容 \3 或$3 匹配第三个分组中的内容 // 使用点元字符var pattern = /g..gle/; // .匹配一个任意字符var str = 'google';alert(pattern.test(str));// 重复匹配var pattern = /g.gle/; // .匹配 0 个一个或多个var str = 'google'; //,?,+,{n,m}alert(pattern.test(str));// 使用字符类匹配var pattern = /g[a-zA-Z_]gle/; // [a-z]表示任意个 a-z 中的字符var str = 'google';alert(pattern.test(str));var pattern = /g[^0-9]gle/; // [^0-9]表示任意个非 0-9 的字符var str = 'google';alert(pattern.test(str));var pattern = /[a-z][A-Z]+/; // [A-Z]+表示 A-Z 一次或多次var str = 'gOOGLE';alert(pattern.test(str));// 使用元符号匹配var pattern = /g\wgle/; // \w匹配任意多个所有字母数字_var str = 'google';alert(pattern.test(str));var pattern = /google\d/; // \d匹配任意多个数字var str = 'google444';alert(pattern.test(str));var pattern = /\D{7,}/; // \D{7,}匹配至少 7 个非数字var str = 'google8';alert(pattern.test(str));// 使用锚元字符匹配var pattern = /^google$/; // ^从开头匹配,$从结尾开始匹配var str = 'google';alert(pattern.test(str));var pattern = /goo\sgle/; // \s 可以匹配到空格var str = 'goo gle';alert(pattern.test(str));var pattern = /google\b/; // \b 可以匹配是否到了边界var str = 'google';alert(pattern.test(str));// 使用或模式匹配var pattern = /google|baidu|bing/; // 匹配三种其中一种字符串var str = 'google';alert(pattern.test(str));// 使用分组模式匹配var pattern = /(google){4,8}/; // 匹配分组里的字符串 4-8 次var str = 'googlegoogle';alert(pattern.test(str));var pattern = /8(.)8/; // 获取 8..8 之间的任意字符var str = 'This is 8google8';str.match(pattern);alert(RegExp.$1); // 得到第一个分组里的字符串内容var pattern = /8(.)8/;var str = 'This is 8google8';var result = str.replace(pattern,'<strong>$1</strong>'); // 得到替换的字符串输出document.write(result);var pattern = /(.)\s(.)/;var str = 'google baidu';var result = str.replace(pattern, '$2 $1'); // 将两个分组的值替换输出document.write(result); 贪婪 惰性 + +? ? ?? ? {n} {n}? {n,} {n,}? {n,m} {n,m}? // 关于贪婪和惰性var pattern = /[a-z]+?/; // ?号关闭了贪婪匹配,只替换了第一个var str = 'abcdefjhijklmnopqrstuvwxyz';var result = str.replace(pattern, 'xxx');alert(result);var pattern = /8(.+?)8/g; // 禁止了贪婪,开启的全局var str = 'This is 8google8, That is 8google8, There is 8google8';var result = str.replace(pattern,'<strong>$1</strong>');document.write(result);var pattern = /8([^8])8/g; // 另一种禁止贪婪var str = 'This is 8google8, That is 8google8, There is 8google8';var result = str.replace(pattern,'<strong>$1</strong>');document.write(result);// 使用 exec 返回数组var pattern = /^[a-z]+\s[0-9]{4}$/i;var str = 'google 2012';alert(pattern.exec(str)); // 返回整个字符串var pattern = /^[a-z]+/i; // 只匹配字母var str = 'google 2012';alert(pattern.exec(str)); // 返回 googlevar pattern = /^([a-z]+)\s([0-9]{4})$/i; // 使用分组var str = 'google 2012';alert(pattern.exec(str)[0]); // google 2012alert(pattern.exec(str)[1]); // googlealert(pattern.exec(str)[2]); // 2012// 捕获性分组和非捕获性分组var pattern = /(\d+)([a-z])/; // 捕获性分组var str = '123abc';alert(pattern.exec(str));var pattern = /(\d+)(?:[a-z])/; // 非捕获性分组var str = '123abc';alert(pattern.exec(str));// 使用分组嵌套var pattern = /(A?(B?(C?)))/; // 从外往内获取var str = 'ABC';alert(pattern.exec(str));// 使用前瞻捕获var pattern = /(goo(?=gle))/; // goo 后面必须跟着 gle 才能捕获var str = 'google';alert(pattern.exec(str));// 使用特殊字符匹配var pattern = /\.\[\/b\]/; // 特殊字符,用\符号转义即可var str = '.[/b]';alert(pattern.test(str));// 使用换行模式var pattern = /^\d+/mg; // 启用了换行模式var str = '1.baidu\n2.google\n3.bing';var result = str.replace(pattern, '');alert(result); 常用的正则 检查邮政编码 var pattern = /[1-9][0-9]{5}/; // 共 6 位数字,第一位不能为 0var str = '224000';alert(pattern.test(str)); 检查文件压缩包 var pattern = /[\w]+\.zip|rar|gz/; // \w 表示所有数字和字母加下划线var str = '123.zip'; // \.表示匹配.,后面是一个选择alert(pattern.test(str)); 删除多余空格 var pattern = /\s/g; // g 必须全局,才能全部匹配var str = '111 222 333';var result = str.replace(pattern,''); // 把空格匹配成无空格alert(result); 删除首尾空格 var pattern = /^\s+/; // 强制首var str = ' goo gle ';var result = str.replace(pattern, '');pattern = /\s+$/; // 强制尾result = result.replace(pattern, '');alert('|' + result + '|');var pattern = /^\s(.+?)\s$/; // 使用了非贪婪捕获var str = ' google ';alert('|' + pattern.exec(str)[1] + '|');var pattern = /^\s(.+?)\s$/;var str = ' google ';alert('|' + str.replace(pattern, '$1') + '|'); // 使用了分组获取 简单的电子邮件验证 var pattern = /^([a-zA-Z0-9_\.\-]+)@([a-zA-Z0-9_\.\-]+)\.([a-zA-Z]{2,4})$/;var str = 'yc60.com@gmail.com';alert(pattern.test(str));var pattern = /^([\w\.\-]+)@([\w\.\-]+)\.([\w]{2,4})$/;var str = 'yc60.com@gmail.com';alert(pattern.test(str)); 3、Function类型 在 ECMAScript 中,Function(函数)类型实际上是对象。每个函数都是 Function 类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针。 函数的声明方式 普通的函数声明 function box(num1, num2) {return num1+ num2;} 使用变量初始化函数 var box= function(num1, num2) {return num1 + num2;}; 使用 Function 构造函数 var box= new Function('num1', 'num2' ,'return num1 + num2'); 第三种方式我们不推荐,因为这种语法会导致解析两次代码(第一次解析常规 ECMAScript 代码,第二次是解析传入构造函数中的字符串),从而影响性能。但我们可以通过这种语法来理解"函数是对象,函数名是指针"的概念。 作为值的函数 ECMAScript 中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。 function box(sumFunction, num) {return sumFunction(num); // someFunction}function sum(num) {return num + 10;}var result = box(sum, 10); // 传递函数到另一个函数里 函数内部属性 在函数内部,有两个特殊的对象:arguments 和 this。arguments 是一个类数组对象,包含着传入函数中的所有参数,主要用途是保存函数参数。但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。 function box(num) {if (num <= 1) {return 1;} else {return num box(num-1); // 一个简单的的递归} } 对于阶乘函数一般要用到递归算法,所以函数内部一定会调用自身;如果函数名不改变是没有问题的,但一旦改变函数名,内部的自身调用需要逐一修改。为了解决这个问题,我们可以使用 arguments.callee 来代替。 function box(num) {if (num <= 1) {return 1;} else {return num arguments.callee(num-1); // 使用 callee 来执行自身} } 函数内部另一个特殊对象是 this,其行为与 Java 和 C中的 this 大致相似。换句话说 ,this 引用的是函数据以执行操作的对象,或者说函数调用语句所处的那个作用域。当在全局作用域中调用函数时,this 对象引用的就是 window。 // 便于理解的改写例子window.color = '红色的'; // 全局的,或者 var color = '红色的';也行alert(this.color); // 打印全局的 colorvar box = {color : '蓝色的', // 局部的 colorsayColor : function () {alert(this.color); // 此时的 this 只能 box 里的 color} };box.sayColor(); // 打印局部的 coloralert(this.color); // 还是全局的// 引用教材的原版例子window.color = '红色的'; // 或者 var color = '红色的';也行var box = {color : '蓝色的'};function sayColor() {alert(this.color); // 这里第一次在外面,第二次在 box 里面}getColor();box.sayColor = sayColor; // 把函数复制到 box 对象里,成为了方法box.sayColor(); 函数属性和方法 ECMAScript 中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性 :length 和 prototype。其中,length 属性表示函数希望接收的命名参数的个数。 function box(name, age) {alert(name + age);}alert(box.length); // 2 对于 prototype 属性,它是保存所有实例方法的真正所在,也就是原型。这个属性 ,我们将在面向对象一章详细介绍。而 prototype 下有两个方法:apply()和 call(),每个函数都包含这两个非继承而来的方法。这两个方法的用途都在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。 function box(num1, num2) {return num1 + num2; // 原函数}function sayBox(num1, num2) {return box.apply(this, [num1, num2]); // this 表示作用域,这里是 window} // []表示 box 所需要的参数function sayBox2(num1, num2) {return box.apply(this, arguments); // arguments 对象表示 box 所需要的参数}alert(sayBox(10,10)); // 20alert(sayBox2(10,10)); // 20 call()方法于 apply()方法相同,他们的区别仅仅在于接收参数的方式不同。对于 call()方法而言,第一个参数是作用域,没有变化,变化只是其余的参数都是直接传递给函数的。 function box(num1, num2) {return num1 + num2;}function callBox(num1, num2) {return box.call(this, num1, num2); // 和 apply 区别在于后面的传参}alert(callBox(10,10)); 事实上,传递参数并不是 apply()和 call()方法真正的用武之地;它们经常使用的地方是能够扩展函数赖以运行的作用域。 var color = '红色的'; // 或者 window.color = '红色的';也行var box = {color : '蓝色的'};function sayColor() {alert(this.color);}sayColor(); // 作用域在 windowsayColor.call(this); // 作用域在 windowsayColor.call(window); // 作用域在 windowsayColor.call(box); // 作用域在 box,对象冒充 这个例子是之前作用域理解的例子修改而成,我们可以发现当我们使用 call(box)方法的时候,sayColor()方法的运行环境已经变成了 box 对象里了。 使用 call()或者 apply()来扩充作用域的最大好处,就是对象不需要与方法发生任何耦合关系(耦合,就是互相关联的意思,扩展和维护会发生连锁反应)。也就是说,box 对象和 sayColor()方法之间不会有多余的关联操作,比如 box.sayColor = sayColor;。 本篇文章为转载内容。原文链接:https://blog.csdn.net/gongxifacai_believe/article/details/108286196。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-01-24 13:01:25
529
转载
转载文章
...装任何插件,只需通过JavaScript即可实现报表精确打印以及打印过程免人工介入。 ------------- 二、特点: 1、高兼容:不需要在浏览器端和服务端安装任何插件,在浏览器插件被各大浏览器纷纷禁用的今天,无插件设计兼容绝大多数浏览器; 2、免安装:软件即拷即用,不安装,不污染操作系统,让操作系统历久弥新; 3、可视化:可视化的模板设计器,通过拖拽即可完成模板设计; 4、高精度:实现精确到毫米的打印精度,对于一些格式复杂,要求精确打印的场合,可以很容易达到毫米级精度; 5、易套打:可视化的模板设计器,在模板中加入一个票据格式的底图,可以很方便地实现套打,对于实现发票、快递面单、支票等打印毫无压力; 6、功能强:从简单报表、主从报表到嵌套报表甚至交叉报表,均能轻松应对。还有一维二维条形码,甚至,还有逆天的脚本功能,只有想不到,没有做不到; 7、自动化: 打印过程中全部自动化,无需象生成PDF、Word、Excel那样还需要人工再点打印; 8、易部署:打印模板既可以部署在客户端(与 cfprint.exe 程序放在同一目录下),也支持部署在服务端随报表数据一起传到客户端; 9、目标活:支持在数据文件中或模板中指定要输出的打印机,发票用针打、报表用激光打、小票用小票机,专机专打; 三、使用前提条件: 1、IE6以上版本、Chrome(谷歌浏览器)4.0以上版本、Firefox 4.0以上版本、Opera 11以上版本、Safari 5.0.2以上版本、iOS 4.2以上版本 或使用Chrome内核、Firefox内核的浏览器均可直接使用本打印系统; 2、在进行打印前,需要先设计好打印模板(模板设计器请见第五节); 3、打印数据必须Json的格式发送给打印服务器,并且数据必须满足指定的格式(见下文); 四、数据格式说明: 下面以一个跨境电商快递面单数据为例解释一下数据各项的含义; { "template": "waybill.fr3", /打印模板文件名。除了指定模板文件以外,还支持把模板嵌入到数据文件中,以实现在服务器端灵活使用打印模板,格式如下:/ /"template": "base64:QTBBRTNEQTE3MkFFQjIzNEFERD<后面省略>" / "ver": 4, /数据模板文件版本/ "Copies": 3, /打印份数,支持指定打印份数/ "Duplex": 1, /是否双面打印,0:默认,不双面,1:垂直,2:水平,3:单面打印(simplex)/ "Printer": "priPrinter", /指定打印机,本系统支持在数据文件中指定打印机,也支持在打印模板中指定打印机/ "PageNumbers": "", /要打印的页码范围,同打印机的打印设置里的格式相同,例如:"1,2,3"表示打印前3页, “2-5”:表示打印第2到5页,“1,2,4-8”表示打印第1、2、4到8页/ "Preview": 1, /是否预览,跟主界面上选择“预览”效果相同,取值为0:不预览,1:预览/ "Tables":[ /数据表数组/ { "Name": "Table1", /表名/ "Cols": [ /字段定义/ { "type": "str", /字段类型,可选值:String,Str,Integer,Int,Smallint,Float,Long, Blob,/ /对于图片、PDF等使用Blob类型,并把值进行Base64编码,并加前缀:/ / "base64/pdf:" 字段值是PDF; "base64/jpg:" 字段值是jpg; "base64/png:" 字段值是png; "base64/gif:" 字段值是gif; / "size": 255, /字段长度/ "name": "HAWB", /字段名称,必须与打印模板中的打印项名称相同/ "required": false /字段是否必填/ }, { "type": "int", "size": 0, "name": "NO", "required": false }, { "type": "float", "size": 0, "name": "报关公司面单号", "required": false }, { "type": "integer", "size": 0, "name": "公司内部单号", "required": false }, { "type": "str", "size": 255, "name": "发件人", "required": false }, { "type": "str", "size": 255, "name": "发件人地址", "required": false }, { "type": "str", "size": 255, "name": "发件人电话", "required": false }, { "type": "str", "size": 255, "name": "发货国家", "required": false }, { "type": "str", "size": 255, "name": "收件人", "required": false }, { "type": "str", "size": 255, "name": "收件人地址", "required": false }, { "type": "str", "size": 255, "name": "收件人电话", "required": false }, { "type": "str", "size": 255, "name": "收货人证件号码", "required": false }, { "type": "str", "size": 255, "name": "收货省份", "required": false }, { "type": "float", "size": 0, "name": "总计费重量", "required": false }, { "type": "int", "size": 0, "name": "总件数", "required": false }, { "type": "float", "size": 0, "name": "申报总价(CNY)", "required": false }, { "type": "float", "size": 0, "name": "申报总价(JPY)", "required": false }, { "type": "int", "size": 0, "name": "件数1", "required": false }, { "type": "str", "size": 255, "name": "品名1", "required": false }, { "type": "float", "size": 0, "name": "单价1(JPY)", "required": false }, { "type": "str", "size": 255, "name": "单位1", "required": false }, { "type": "float", "size": 0, "name": "申报总价1(CNY)", "required": false }, { "type": "float", "size": 0, "name": "申报总价1(JPY)", "required": false }, { "type": "int", "size": 0, "name": "件数2", "required": false }, { "type": "str", "size": 255, "name": "品名2", "required": false }, { "type": "float", "size": 0, "name": "单价2(JPY)", "required": false }, { "type": "str", "size": 255, "name": "单位2", "required": false }, { "type": "float", "size": 0, "name": "申报总价2(CNY)", "required": false }, { "type": "float", "size": 0, "name": "申报总价2(JPY)", "required": false }, { "type": "AutoInc", "size": 0, "name": "ID", "required": false }, { "type": "blob", "size": 0, "name": "附件", "required": false } ], "Data": [ /数据行定义,每一行含义见上面的字段定义/ { "HAWB": "860014010055", "NO": 1, "报关公司面单号": 200303900791, "公司内部单号": 730293, "发件人": "NAKAGAWA SUMIRE 2", "发件人地址": " 991-199-113,Kameido,Koto-ku,Tokyo", "发件人电话": "03-3999-3999", "发货国家": "日本", "收件人": "张三丰", "收件人地址": "上海市闵行区虹梅南路1660弄蔷薇八村99号9999室", "收件人电话": "182-1234-8888", "收货人证件号码": null, "收货省份": null, "总计费重量": 3.2, "总件数": 13, "申报总价(CNY)": null, "申报总价(JPY)": null, "件数1": 10, "品名1": "纸尿片", "单价1(JPY)": null, "单位1": null, "申报总价1(CNY)": null, "申报总价1(JPY)": null, "件数2": null, "品名2": null, "单价2(JPY)": null, "单位2": null, "申报总价2(CNY)": null, "申报总价2(JPY)": null, "ID": 1, "附件": "base64/pdf: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IDI3OCAyNzgKMjc4IDI3OCAyNzggMjc4IDI3OCAyNzggMjc4IDI3OCAyNzggMjc4IDI3OCAyNzggMjc4IDI3OCAyNzggMjc4CjI3OCA1NTYgNTU2IDMzMyA1NTYgNTU2IDU1NiA1NTYgMjc4IDY2NyAyNzggMjc4IDI3OCAyNzggMjc4IDY2NwoyNzggNjY3IDI3OCAyNzggMjc4IDI3OCAyNzggNjY3IDI3OCA2NjcgMjc4IDY2NyAyNzggNjY3IDI3OCAyNzgKMjc4IDY2NyAyNzggNjY3IDU1MiAyNzggMjc4IDI3OCAyNzggNTU2IDI3OCA1NTYgMjc4IDI3OCAyNzggNjY3CjI3OCA2NjcgMjc4IDI3OCAyNzggNjY3IDI3OCA2NjcgMjc4IDY2NyAyNzggNjY3IDI3OCA2NjcgMjc4IDI3OF0KL0VuY29kaW5nL1dpbkFuc2lFbmNvZGluZwovRm9udERlc2NyaXB0b3IgMTEgMCBSCj4+CmVuZG9iagoxMSAwIG9iago8PAovVHlwZS9Gb250RGVzY3JpcHRvcgovRm9udE5hbWUgL0FyaWFsTVQKL0ZsYWdzIDMyCi9Gb250QkJveFstNjY1IC0zMjUgMjAwMCAxMDA2XQovU3RlbVYgOTUKL0l0YWxpY0FuZ2xlIDAKL0NhcEhlaWdodCA5MDUKL0FzY2VudCA5MDUKL0Rlc2NlbnQgLTIxMgo+PgplbmRvYmoKMyAwIG9iago8PAovVHlwZS9QYWdlcwovQ291bnQgMQovS2lkc1s0IDAgUl0KPj4KZW5kb2JqCjIgMCBvYmoKPDwKL1R5cGUvQ2F0YWxvZwovUGFnZXMgMyAwIFIKL1BhZ2VMYXlvdXQvU2luZ2xlUGFnZQovVmlld2VyUHJlZmVyZW5jZXMgMTIgMCBSCj4+CmVuZG9iagoxMiAwIG9iago8PAovVHlwZS9WaWV3ZXJQcmVmZXJlbmNlcwo+PgplbmRvYmoKeHJlZgowIDEzCjAwMDAwMDAwMDAgNjU1MzUgZg0KMDAwMDAwMDAxNiAwMDAwMCBuDQowMDAwMDA0MjEzIDAwMDAwIG4NCjAwMDAwMDQxNTggMDAwMDAgbg0KMDAwMDAwMDcxNiAwMDAwMCBuDQowMDAwMDAwMjQxIDAwMDAwIG4NCjAwMDAwMDA4NzIgMDAwMDAgbg0KMDAwMDAwMjkyNyAwMDAwMCBuDQowMDAwMDAxMjQ1IDAwMDAwIG4NCjAwMDAwMDEwNTUgMDAwMDAgbg0KMDAwMDAwMTU2MiAwMDAwMCBuDQowMDAwMDAzOTg5IDAwMDAwIG4NCjAwMDAwMDQzMTAgMDAwMDAgbg0KdHJhaWxlcgo8PAovU2l6ZSAxMwovSW5mbyAxIDAgUgovUm9vdCAyIDAgUgovSURbPDVBMkU0QzkzOTdENEU0RDE3NkIwOTBDRUU3OTMxMzRGPjw1QTJFNEM5Mzk3RDRFNEQxNzZCMDkwQ0VFNzkzMTM0Rj5dCj4+CnN0YXJ0eHJlZgo0MzU2CiUlRU9GCg==", }, { "HAWB": "860014010035", "NO": 2, "报关公司面单号": 200303900789, "公司内部单号": 730291, "发件人": "NAKAGAWA SUMIRE", "发件人地址": " 991-199-113,Kameido,Koto-ku,Tokyo", "发件人电话": "03-3999-3999", "发货国家": "日本", "收件人": "张无忌", "收件人地址": "上海市闵行区虹梅南路1660弄蔷薇八村88号8888室", "收件人电话": "182-1234-8888", "收货人证件号码": null, "收货省份": null, "总计费重量": 3.2, "总件数": 13, "申报总价(CNY)": null, "申报总价(JPY)": null, "件数1": 10, "品名1": "纸尿片", "单价1(JPY)": null, "单位1": null, "申报总价1(CNY)": null, "申报总价1(JPY)": null, "件数2": null, "品名2": null, "单价2(JPY)": null, "单位2": null, "申报总价2(CNY)": null, "申报总价2(JPY)": null, "ID": 2, "附件":"base64/gif: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" } ] }, { "Name": "Table2", "Cols": [ { "type": "int", "size": 0, "name": "NO", "required": false }, { "type": "float", "size": 0, "name": "订单编号", "required": false }, { "type": "integer", "size": 0, "name": "下单日期", "required": false }, { "type": "str", "size": 255, "name": "下单平台", "required": false } ], "Data": [ { "NO": 1, "订单编号": 200303900791, "下单日期": "2017-01-20", "下单平台": "天猫" }, { "NO": 2, "订单编号": 200303900792, "下单日期": "2017-01-20", "下单平台": "京东" } ] } ] } 五、调用示例: <!-- ★★★ 模式1 ★★★ --> <!DOCTYPE html> <head> <meta charset="utf-8" /> <title>康虎云报表系统测试</title> </head> <body> <div style="width: 100%;text-align:center;"> <h2>康虎云报表系统</h2> <h3>打印测试(模式1)</h3> <div> <input type="button" id="btnPrint" value="打印" onClick="doSend(_reportData);" /> </div> </div> <div id="output"></div> </body> <script type="text/javascript"> //定义数据脚本 var _reportData = '{"template":"waybill.fr3","Cols":[{"type":"str","size":255,"name":"HAWB","required":false},<这里省略1000字> ]}'; //在浏览器控制台输出调试信息 console.log("reportData = " + _reportData); </script> <script language="javascript" type="text/javascript" src="cfprint.min.js"></script> <script language="javascript" type="text/javascript" src="cfprint_ext.js"></script> <script language="javascript" type="text/javascript"> /下面四个参数必须放在myreport.js脚本后面,以覆盖myreport.js中的默认值/ var _delay_send = 1000; //发送打印服务器前延时时长,-1则表示不自动打印 var _delay_close = 1000; //打印完成后关闭窗口的延时时长, -1则表示不关闭 var cfprint_addr = "127.0.0.1"; //打印服务器监听地址 var cfprint_port = 54321; //打印服务器监听端口 </script> </html> <!-- ★★★ 模式2 ★★★ --> <?php //如果有php运行环境,只需把该文件扩展名改成 .php,然后上传到web目录即可在真实服务器上测试 header("Access-Control-Allow-Origin: "); ?> <!DOCTYPE html> <head> <meta charset="utf-8" /> <title>康虎云报表系统测试</title> <style type="text/css"> output {font-size: 12px; background-color:F0FFF0;} </style> </head> <body> <div style="width: 100%;text-align:center;"> <h2>康虎云报表系统(Ver 1.3.0)</h2> <h3>打印测试(模式2)</h3> <div style="line-height: 1.5;"> <div style="width: 70%; text-align: left;"> <b>一、首先按下列步骤设置:</b><br/> 1、运行打印服务器;<br/> 2、按“停止”按钮停止服务;<br/> 3、打开“设置”区;<br/> 4、在“常用参数-->服务模式”中,选择“模式2”;<br/> 5、按“启动”按钮启动服务。 </div> <div style="width: 70%; text-align: left;"> <b>二、按本页的“打印”按钮开始打印。</b><br/> </div><br/> <input type="button" id="btnPrint" value="打印" /><br/><br/> <div style="width: 70%; text-align: left; font-size: 12px;"> 由于JavaScript在不同域名下访问会出现由来已久的跨域问题,所以正式部署到服务器使用时,要解决跨域问题。<br/> 对于IE8以上版本浏览器,只需增加一个reponse头:Access-Control-Allow-Origin即可,而对于php、jsp、asp/aspx等动态语言而言,增加一个response头是非常简单的事,例如:<br/> <b>在php:</b><br/><span style="color: red;"> <?php <br/> header("Access-Control-Allow-Origin: ");<br/> ?><br/> </span> <b>在jsp:</b><br/><span style="color: red;"> <% <br/> response.setHeader("Access-Control-Allow-Origin", ""); <br/> %><br/> </span> <b>在asp.net中:</b><br/><span style="color: red;"> Response.AppendHeader("Access-Control-Allow-Origin", ""); </span>,<br/>其他语言里,大家请自行搜索“ajax跨域”。而对于IE8以下的浏览器,大家可以自行搜索“IE6+Ajax+跨域”寻找解决办法吧,也可以联系我们帮助。 </div> </div> </div> <div id="output"></div> </body> <!-- 引入模式2所需的javascript支持库 --> <script type="text/javascript" src="cfprint_mode2.min.js" charset="UTF-8"></script> <!-- 构造报表数据 --> <script type="text/javascript"> var _reportData = '{"template":"waybill.fr3","ver":3, "Tables":[ {"Name":"Table1", "Cols":[{"type":"str","size":255,"name":"HAWB","required":false},{"type":"int","size":0,"name":"NO","required":false},{"type":"float","size":0,"name":"报关公司面单号","required":false},{"type":"integer","size":0,"name":"公司内部单号","required":false},{"type":"str","size":255,"name":"发件人","required":false},{"type":"str","size":255,"name":"发件人地址","required":false},{"type":"str","size":255,"name":"发件人电话","required":false},{"type":"str","size":255,"name":"发货国家","required":false},{"type":"str","size":255,"name":"收件人","required":false},{"type":"str","size":255,"name":"收件人地址","required":false},{"type":"str","size":255,"name":"收件人电话","required":false},{"type":"str","size":255,"name":"收货人证件号码","required":false},{"type":"str","size":255,"name":"收货省份","required":false},{"type":"float","size":0,"name":"总计费重量","required":false},{"type":"int","size":0,"name":"总件数","required":false},{"type":"float","size":0,"name":"申报总价(CNY)","required":false},{"type":"float","size":0,"name":"申报总价(JPY)","required":false},{"type":"int","size":0,"name":"件数1","required":false},{"type":"str","size":255,"name":"品名1","required":false},{"type":"float","size":0,"name":"单价1(JPY)","required":false},{"type":"str","size":255,"name":"单位1","required":false},{"type":"float","size":0,"name":"申报总价1(CNY)","required":false},{"type":"float","size":0,"name":"申报总价1(JPY)","required":false},{"type":"int","size":0,"name":"件数2","required":false},{"type":"str","size":255,"name":"品名2","required":false},{"type":"float","size":0,"name":"单价2(JPY)","required":false},{"type":"str","size":255,"name":"单位2","required":false},{"type":"float","size":0,"name":"申报总价2(CNY)","required":false},{"type":"float","size":0,"name":"申报总价2(JPY)","required":false},{"type":"int","size":0,"name":"件数3","required":false},{"type":"str","size":255,"name":"品名3","required":false},{"type":"float","size":0,"name":"单价3(JPY)","required":false},{"type":"str","size":255,"name":"单位3","required":false},{"type":"float","size":0,"name":"申报总价3(CNY)","required":false},{"type":"float","size":0,"name":"申报总价3(JPY)","required":false},{"type":"int","size":0,"name":"件数4","required":false},{"type":"str","size":255,"name":"品名4","required":false},{"type":"float","size":0,"name":"单价4(JPY)","required":false},{"type":"str","size":255,"name":"单位4","required":false},{"type":"float","size":0,"name":"申报总价4(CNY)","required":false},{"type":"float","size":0,"name":"申报总价4(JPY)","required":false},{"type":"int","size":0,"name":"件数5","required":false},{"type":"str","size":255,"name":"品名5","required":false},{"type":"float","size":0,"name":"单价5(JPY)","required":false},{"type":"str","size":255,"name":"单位5","required":false},{"type":"float","size":0,"name":"申报总价5(CNY)","required":false},{"type":"float","size":0,"name":"申报总价5(JPY)","required":false},{"type":"str","size":255,"name":"参考号","required":false},{"type":"AutoInc","size":0,"name":"ID","required":false}],"Data":[{"公司内部单号":730293,"发货国家":"日本","单价1(JPY)":null,"申报总价2(JPY)":null,"单价4(JPY)":null,"申报总价2(CNY)":null,"申报总价5(JPY)":null,"报关公司面单号":200303900791,"申报总价5(CNY)":null,"收货人证件号码":null,"申报总价1(JPY)":null,"单价3(JPY)":null,"申报总价1(CNY)":null,"申报总价4(JPY)":null,"申报总价4(CNY)":null,"收件人电话":"182-1758-9999","收件人地址":"上海市闵行区虹梅南路1660弄蔷薇八村139号502室","HAWB":"860014010055","发件人电话":"03-3684-9999","发件人地址":" 1-1-13,Kameido,Koto-ku,Tokyo","NO":3,"ID":3,"单价2(JPY)":null,"申报总价3(JPY)":null,"单价5(JPY)":null,"申报总价3(CNY)":null,"收货省份":null,"申报总价(JPY)":null,"申报总价(CNY)":null,"总计费重量":3.20,"收件人":"张三丰2","总件数":13,"品名5":null,"品名4":null,"品名3":null,"品名2":null,"品名1":"纸尿片","参考号":null,"发件人":"NAKAGAWA SUMIRE 2","单位5":null,"单位4":null,"单位3":null,"单位2":null,"单位1":null,"件数5":null,"件数4":null,"件数3":3,"件数2":null,"件数1":10},{"公司内部单号":730291,"发货国家":"日本","单价1(JPY)":null,"申报总价2(JPY)":null,"单价4(JPY)":null,"申报总价2(CNY)":null,"申报总价5(JPY)":null,"报关公司面单号":200303900789,"申报总价5(CNY)":null,"收货人证件号码":null,"申报总价1(JPY)":null,"单价3(JPY)":null,"申报总价1(CNY)":null,"申报总价4(JPY)":null,"申报总价4(CNY)":null,"收件人电话":"182-1758-9999","收件人地址":"上海市闵行区虹梅南路1660弄蔷薇八村139号502室","HAWB":"860014010035","发件人电话":"03-3684-9999","发件人地址":" 1-1-13,Kameido,Koto-ku,Tokyo","NO":1,"ID":1,"单价2(JPY)":null,"申报总价3(JPY)":null,"单价5(JPY)":null,"申报总价3(CNY)":null,"收货省份":null,"申报总价(JPY)":null,"申报总价(CNY)":null,"总计费重量":3.20,"收件人":"张三丰","总件数":13,"品名5":null,"品名4":null,"品名3":null,"品名2":null,"品名1":"纸尿片","参考号":null,"发件人":"NAKAGAWA SUMIRE","单位5":null,"单位4":null,"单位3":null,"单位2":null,"单位1":null,"件数5":null,"件数4":null,"件数3":3,"件数2":null,"件数1":10},{"公司内部单号":730292,"发货国家":"日本","单价1(JPY)":null,"申报总价2(JPY)":null,"单价4(JPY)":null,"申报总价2(CNY)":null,"申报总价5(JPY)":null,"报关公司面单号":200303900790,"申报总价5(CNY)":null,"收货人证件号码":null,"申报总价1(JPY)":null,"单价3(JPY)":null,"申报总价1(CNY)":null,"申报总价4(JPY)":null,"申报总价4(CNY)":null,"收件人电话":"182-1758-9999","收件人地址":"上海市闵行区虹梅南路1660弄蔷薇八村139号502室","HAWB":"860014010045","发件人电话":"03-3684-9999","发件人地址":" 1-1-13,Kameido,Koto-ku,Tokyo","NO":2,"ID":2,"单价2(JPY)":null,"申报总价3(JPY)":null,"单价5(JPY)":null,"申报总价3(CNY)":null,"收货省份":null,"申报总价(JPY)":null,"申报总价(CNY)":null,"总计费重量":3.20,"收件人":"张无忌","总件数":13,"品名5":null,"品名4":null,"品名3":null,"品名2":null,"品名1":"纸尿片","参考号":null,"发件人":"NAKAGAWA SUMIRE 1","单位5":null,"单位4":null,"单位3":null,"单位2":null,"单位1":null,"件数5":null,"件数4":null,"件数3":3,"件数2":null,"件数1":10}]}]}'; if(window.console) console.log("reportData = " + _reportData); </script> <!-- 设置服务器参数 --> <script language="javascript" type="text/javascript"> var cfprint_addr = "127.0.0.1"; //打印服务器监听地址 var cfprint_port = 54321; //打印服务器监听端口 var _url = "http://"+cfprint_addr+":"+cfprint_port; </script> <!-- 编写回调函数用以处理服务器返回的数据 --> <script type="text/javascript"> / 参数: readyState: XMLHttpRequest的状态 httpStatus: 服务端返回的http状态 responseText: 服务端返回的内容 / var callbackSuccess = function(readyState, httpStatus, responseText){ if (httpStatus === 200) { //{"result": 1, "message": "打印完成"} var response = CFPrint.parseJSON(responseText); alert(response.message+", 状态码["+response.result+"]"); }else{ alert('打印失败,HTTP状态代码是:'+httpStatus); } } / 参数: message: 错误信息 / var callbackFailed = function(message){ alert('发送打印任务出错: ' + message); } </script> <!-- 调用发送打印请求功能 --> <script type="text/javascript"> (function(){ document.getElementById("btnPrint").onclick = function() { CFPrint.outputid = "output"; //指定调试信息输出div的id CFPrint.SendRequest(_url, _reportData, callbackSuccess, callbackFailed); //发送打印请求 }; })(); </script> </html> 六、模板设计器(重要!重要!!,好多朋友都找不到设计器入口) 在主界面上,双击右下角的“设计”两个字,即可打开模板设计工具箱,在工具箱有三个按钮和一个大文本框。三个按钮的作用分别是: 设计:以大文本框中的json数据为数据源,打开模板设计器窗口; 预览:以大文本框中的json数据为数据源,预览当前所用模板的打印效果; 打印:以大文本框中的json数据为数据源,向打印机输出当前所用模板生成的报表; 以后将会有详细的模板设计教程发布,如果您遇到紧急的难题,请向作者咨询。 本篇文章为转载内容。原文链接:https://blog.csdn.net/chensongmol/article/details/76087600。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-04-01 18:34:12
234
转载
转载文章
...汰,基于HTML5和JavaScript的新一代跨站脚本攻击手段正被恶意攻击者广泛利用。 同时,针对CSRF漏洞的防御研究也在不断深化,各大云服务商如AWS、阿里云等相继推出更为精细的防护策略,通过强化身份验证机制、实施严格的请求来源检查以及优化token管理,有效降低了CSRF攻击的风险。而在防止持久型XSS方面,一些前沿的Web框架已开始采用自动转义和上下文相关的编码策略,显著提升了对数据库存储数据的安全处理能力。 值得注意的是,为了应对愈发复杂的Web安全挑战,各国政府和行业组织正积极推动相关法律法规的制定和完善,例如欧盟GDPR法规要求企业加强用户数据保护,包括防范SQL注入、XSS等可能导致数据泄露的安全威胁。与此同时,开发者社区也在积极响应,提倡“安全左移”理念,将安全性融入开发周期的每个阶段,从源头上降低Web安全风险。 综上所述,在实际操作中,广大开发者和安全从业者不仅需要掌握文章所述的基础知识,更应密切关注行业动态和最新研究成果,以提升Web应用程序的安全性,并确保用户的隐私信息得到有效保护。
2023-01-03 14:51:12
493
转载
建站模板下载
...绍 该“简约电子邮件客户端下载页面模板”专为科技公司与研发企业设计,集科技创新元素于一体,适用于构建邮件相关产品的展示与下载页面。模板以科技风格为核心,提供专业且直观的布局,旨在提升用户体验并促进电子邮件客户端软件的高效推广。用户可通过此模板快速创建拥有科技感的网站页面,实现便捷的下载功能,满足更多科技企业的数字化需求。 点我下载 文件大小:1.22 MB 您将下载一个资源包,该资源包内部文件的目录结构如下: 本网站提供模板下载功能,旨在帮助广大用户在工作学习中提升效率、节约时间。 本网站的下载内容来自于互联网。如您发现任何侵犯您权益的内容,请立即告知我们,我们将迅速响应并删除相关内容。 免责声明:站内所有资源仅供个人学习研究及参考之用,严禁将这些资源应用于商业场景。 若擅自商用导致的一切后果,由使用者承担责任。
2023-05-07 20:12:02
91
本站
JQuery插件下载
...lob对象,以支持在客户端直接进行图像操作。其核心功能在于能够在不影响原始图片质量的前提下,在图片的指定位置添加包含文本或其他图形元素的水印,从而实现版权保护、品牌标识或其他个性化需求。使用该插件时,开发者可以通过简单的配置选项来自定义水印内容,如设置水印文字(如'我是水印素材')、字体样式(例如'MicrosoftYaHei'或'Arial')、字号大小(例如18px)、颜色(默认为白色,可设为任意十六进制颜色值)以及水印在图片上的具体位置坐标(如X轴位置180px)。此外,尽管此插件功能强大,但在本地环境预览时需要注意可能存在的跨域问题,实际部署时需要配合服务器环境来确保正常运行。总之,jquery图片水印插件Img2Blob.js提供了一种高效且便捷的方式,使得网页开发者无需依赖复杂的后端服务就能实现前端图片的实时水印处理,极大地增强了Web应用中的图片管理和展示功能。 点我下载 文件大小:93.72 KB 您将下载一个JQuery插件资源包,该资源包内部文件的目录结构如下: 本网站提供JQuery插件下载功能,旨在帮助广大用户在工作学习中提升效率、节约时间。 本网站的下载内容来自于互联网。如您发现任何侵犯您权益的内容,请立即告知我们,我们将迅速响应并删除相关内容。 免责声明:站内所有资源仅供个人学习研究及参考之用,严禁将这些资源应用于商业场景。 若擅自商用导致的一切后果,由使用者承担责任。
2023-01-05 14:31:31
466
本站
Docker
...署VirtualGL客户端来达成的。不过,有些程序员在运用VirtualGL进行拓宽屏幕时,发现连接上之后只能看到一个黑屏,无法正常运用。 如果碰到了这个故障,处理方法如下: 1. 将VirtualGL客户端中的/etc/X11/xorg.conf文件替换为系统中的xorg.conf文件。 2. 部署Xorg并创建OpenGL配置文件。 3. 在xorg.conf文件中添加如下配置选项: Option "UseDisplayDevice" "none" Virtual 2048 2048 通过以上操作,便可以处理运用docker进行拓宽屏幕时碰到的黑屏故障。 总之,程序员运用docker进行拓宽屏幕时,需要注意部署VirtualGL客户端,并按照上述方法进行配置,避免碰到黑屏故障。
2023-09-04 23:41:28
583
电脑达人
MySQL
...密技术保护MySQL客户端与服务器之间的通信,也是防止中间人攻击、保障密码传输安全的重要手段。 对于忘记MySQL密码的情况,除了上述提到的通过命令行工具以具有足够权限的用户重置密码外,还可以借助第三方MySQL管理工具,如phpMyAdmin、Navicat等,它们通常提供了更为直观的操作界面来处理这类问题,大大降低了数据库管理的门槛。 综上所述,MySQL账号和密码的管理不仅涉及到查询和重置这些基本操作,更涵盖了数据库访问控制、密码加密存储、安全审计等多个层面,需要结合最新的安全技术和最佳实践,以实现对MySQL数据库的有效安全管理。
2024-01-21 10:37:36
52
算法侠
MySQL
...数据库连接故障指的是客户端应用程序与MySQL服务器之间的通信出现问题,无法建立或维持有效的连接状态。可能的原因包括但不限于服务器未运行、网络中断、登录凭据错误(如用户名、密码不正确)、连接超时等。在本文的上下文中,数据库连接故障可能导致用户即使拥有正确的数据库和表名,也无法成功访问到所需的数据库表。
2023-11-28 12:42:54
55
算法侠
MySQL
...通过MySQL命令行客户端查找MySQL版本号。 1. 启动MySQL命令行客户端。 2. 键入命令 "SELECT VERSION();",然后按Enter键。 3. MySQL版本号将显示在MySQL命令行客户端中。 例如: mysql>SELECT VERSION(); +-------------------------+ | VERSION() | +-------------------------+ | 5.7.19-0ubuntu0.16.04.1 | +-------------------------+ 1 row in set (0.00 sec) 无论您选择哪种方法,从中获得的MySQL版本号都是相同的。查看MySQL版本号是一个重要的工作,因为MySQL的版本可能会改变,从而可能会引起应用程序或Web应用程序的行为也随之发生改变。
2023-10-03 21:22:15
106
软件工程师
Docker
...。通过端口映射,外部客户端可以通过访问主机的 IP 地址及指定端口号,间接访问到容器内运行的服务,实现了容器内外网络通信的桥梁作用。 docker run , docker run 是 Docker 容器生命周期管理中的一个重要命令,用于启动一个新的容器实例。该命令可以一次性完成拉取镜像、创建容器并启动容器等一系列操作。在本文中,docker run -p 参数组合被用来执行端口映射,即将主机端口与容器端口对应起来,使得外部可以直接访问主机IP和指定端口来连接到容器内部的服务。 NetworkSettings.Networks , 在 Docker 容器的 inspect 输出信息中,NetworkSettings.Networks 表示容器在网络配置方面的详细信息,包括容器加入的所有网络及其对应的网络接口设置。在本文中,通过 docker inspect 命令结合 --format 参数和特定模板语法查询容器的 IPAddress,获取的是当前容器在某一网络下的内部 IP 地址,这对于需要直接基于容器内部 IP 访问其服务的场景尤为关键。
2023-09-21 17:15:59
837
电脑达人
Docker
...d”作为默认的NTP客户端,在集群层面进一步提升了容器间的时间同步能力。 总的来说,面对Docker及容器技术中的时钟同步挑战,开发者和运维人员需要密切关注相关领域的最新进展,结合自身应用场景选择合适的同步策略和技术手段,以确保系统的稳定性和数据的一致性。
2023-10-26 12:53:07
467
程序媛
Docker
...080端口,这样外部客户端就可以通过访问宿主机的8080端口来访问到Nginx服务器提供的服务。
2023-06-15 13:54:04
280
编程狂人
VUE
...e.js是一个普遍的JavaScript框架,用于构建互动的Web界面设计。它供给了一个响应式且易于理解的API,使得构建繁复的Web应用程序变得更为简易。 在电商网站中,Sku(Stock Keeping Unit)是指货品的唯一编码,通过Sku可以辨别各类、尺码、颜色的商品。而使用Vue.js来完成Sku选择器,可以为客户供给更好的商品选择体验。 <template> <div> <div v-for="item in skuList"> <h3>{ { item.title } }</h3> <div v-for="subItem in item.items"> <label> <input type="checkbox" v-model="selected[subItem.id]" @change="onSkuSelected" /> { { subItem.value } } </label> </div> </div> </div> </template> 在上面的代码中,我们使用Vue.js的v-for命令展现Sku列表,并使用v-model命令关联选择的状态。当用户勾选或取消勾选选项时,通过@change事件启动onSkuSelected方法来处理选择状态。 除了Sku选择器,Vue.js还可以用于完成许多其他的功能,例如页面展现、表单验证、事件处理等。因此,Vue.js已经成为许多开发者选择的第一框架。
2023-05-19 22:11:19
101
算法侠
MySQL
...是MySQL服务监听客户端连接的本地文件路径,MySQL服务器通过这个套接字文件与其他应用程序(如PHP、Python等)建立本地连接,而非通过TCP/IP端口进行远程连接。 find命令 , find命令是Linux及类Unix操作系统中的一个强大实用程序,用于在指定目录下查找满足特定条件的文件或目录。在文章中提到的场景中,find ./ -name mysqld这条命令是在/usr/bin目录及其子目录下搜索名为\ mysqld\ 的文件,以便确定MySQL服务器二进制文件的确切路径。该命令根据用户提供的条件来遍历文件系统树,返回符合条件的文件或目录的完整路径名,从而帮助用户找到MySQL的安装路径。
2023-12-31 14:25:35
112
软件工程师
MySQL
...装有了 MySQL 客户端mysql--version MySQL 客户端是接入 MySQL 服务端的软件,如果你没有装有 MySQL 客户端,那么你将无法接入到 MySQL 服务端。在命令行中输入上面的指令,如果系统提示找不到该命令,则说明你还没有装有 MySQL 客户端。 2. 查看是否装有了 MySQL 服务端mysql-u root -p -h localhost MySQL 服务端是 MySQL 数据库的关键,如果你没有装有 MySQL 服务端,那么你将无法利用 MySQL。在命令行中输入上面的指令,如果系统提示找不到该命令,则说明你还没有装有 MySQL 服务端。 3. 查看是否装有了 MySQL 的 Python 插件包import pymysql;print(pymysql.__version__) 对于 Python 开发者来说,他们须要在电脑中装有 MySQL 的 Python 插件包,才能在个人的 Python 项目中利用 MySQL。在 Python 命令行中输入上面的指令,如果系统提示找不到该模块,则说明你还没有装有 MySQL 的 Python 插件包。 通过上述三个步骤,你就可确认出个人的电脑是否已经装有 MySQL。若未装有,可以到 MySQL 的官网上下载相应的软件,并按照提示开展装有。
2023-04-24 15:12:40
49
电脑达人
MySQL
...它可以持续监听并响应客户端请求,处理包括连接管理、查询执行在内的数据库操作。在文章中提到,用户通过命令行工具初始化MySQL服务,并使用特定参数以管理员权限启动该服务,确保MySQL数据库能够正常运行和提供数据服务。 bin文件夹 , 在软件安装目录中,bin(binary的缩写)文件夹通常包含了一组用于执行程序、脚本和其他必要的二进制文件。对于MySQL来说,其bin目录下存放了诸如mysqld(MySQL服务器)、mysql(命令行客户端)等关键可执行文件,用户通过调用这些文件来进行MySQL数据库的安装、配置、启动、停止和管理等各种操作。
2023-11-16 22:43:19
84
键盘勇士
站内搜索
用于搜索本网站内部文章,支持栏目切换。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
bg %jobnumber
- 将挂起的作业置于后台继续运行。
推荐内容
推荐本栏目内的其它文章,看看还有哪些文章让你感兴趣。
2023-04-28
2023-08-09
2023-06-18
2023-04-14
2023-02-18
2023-04-17
2024-01-11
2023-10-03
2023-09-09
2023-06-13
2023-08-07
2023-03-11
历史内容
快速导航到对应月份的历史文章列表。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"