eb前端开发中,树形级联菜单是一种常见的交互组件,通过层级结构展示信息并支持选择操作。本文将以代码为例,分步介绍如何实现一个树形级联菜单。无论你是否具备相关经验,都能轻松掌握这一技能。
树形结构是一种非线性数据结构,由节点和边组成。每个节点可以有多个子节点,而根节点没有父节点。在实现树形级联菜单之前,我们需要了解树的基本概念。
我们从创建一个基础的HTML文件开始,命名为index.html,并添加必要的样式和脚本引用。在HTML的 <body> 标签内,我们添加一个空白的 <ul> 元素,这将作为树形菜单的容器。
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tree Menu</title>
<link rel="stylesheet" href="styles.css">
<script src="main.js"></script>
</head>
<body>
<ul id="tree-menu"></ul>
</body>
</html>
为了模拟树形数据,我们可以定义一个包含层次结构的JSON对象。这里以一个网络设备目录作为示例,数据结构如下所示:
JavaScript
const data = [
{
label: 'Device 1',
children: [
{
label: 'Subdevice 1-1',
children: []
},
{
label: 'Subdevice 1-2',
children: [
{
label: 'Subdevice 1-2-1',
children: []
}
]
}
]
},
{
label: 'Device 2',
children: []
}
];
我们通过document.getElementById("tree-menu")获取树形菜单的容器,然后递归遍历数据对象,将每个节点生成为菜单项,并添加到容器中。`
JavaScript
function buildTree(menuContainer, data) {
data.forEach(item => {
const li = document.createElement('li');
li.innerText = item.label;
if (item.children.length > 0) {
const ul = document.createElement('ul');
buildTree(ul, item.children);
li.appendChild(ul);
}
menuContainer.appendChild(li);
});
}
const treeMenu = document.getElementById('tree-menu');
buildTree(treeMenu, data);
通过添加自定义的CSS样式和JavaScript事件处理,我们可以实现树形菜单的展开与折叠功能。用户点击菜单项时,相应的子菜单将显示或隐藏。
CSS
#tree-menu ul {
display: none;
}
#tree-menu li.collapsed > ul {
display: block;
}
以上代码将初始状态下的子菜单隐藏,当菜单项的父级li元素带有collapsed类名时,显示对应的子菜单。
JavaScript
document.querySelectorAll('#tree-menu li').forEach(li => {
const subMenu = li.querySelector('ul');
if (subMenu) {
li.addEventListener('click', () => {
li.classList.toggle('collapsed');
});
}
});
通过以上代码,当用户点击带有子菜单项的菜单项时,通过添加或移除collapsed类名,实现子菜单的显示或隐藏。
在树形级联菜单中,我们经常需要获取用户所选的值,并将其用于后续的数据交互。为了实现这一功能,我们可以为每个菜单项添加一个点击事件处理函数,并将所选的值存储在全局变量中。
首先,在JavaScript代码中,声明一个全局变量selectedValue用于存储用户所选的值:
JavaScript
let selectedValue = '';
document.querySelectorAll('#tree-menu li').forEach(li => {
li.addEventListener('click', (e) => {
selectedValue = li.innerText;
// 阻止事件冒泡
e.stopPropagation();
});
});
然后,当用户点击任意菜单项时,相应的点击事件将触发,将该菜单项的文本内容赋值给selectedValue变量。
在后续的数据交互过程中,我们可以使用selectedValue变量来获取用户所选的值,并进行相应的处理。
希望本文能够对您有所帮助,感谢您的阅读!
人人为我,我为人人,谢谢您的浏览,我们一起加油吧。
Web前端开发中,树形级联菜单,是一种常见且实用的界面交互组件。它不仅可以提供清晰的导航和大量信息分类展示,还能让用户更方便地进行操作和查询。然而,除了其直观的功能外,树形级联菜单,还可以被用于学习和应用CSS选择器以及CSS技巧。本文将通过代码和实例,分步骤地讲解如何通过树形级联菜单,来理解和运用CSS选择器与CSS技巧。
接下来,我们通过上一篇文章的例子,来了解本文的信息点。
HTML
<ul id="tree-menu">
<li><label>Device 1</label>
<ul>
<li><label>Subdevice 1-1</label></li>
<li><label>Subdevice 1-2</label>
<ul>
<li><label>Subdevice 1-2-1</label></li>
<li><label>Subdevice 1-2-2</label></li>
<li><label>Subdevice 1-2-3</label></li>
<li><label>Subdevice 1-2-4</label></li>
<li><label>Subdevice 1-2-5</label></li>
<li><label>Subdevice 1-2-6</label></li>
<li><label>Subdevice 1-2-7</label></li>
<li><label>Subdevice 1-2-8</label></li>
<li><label>Subdevice 1-2-9</label></li>
</ul>
</li>
</ul>
</li>
<li><label>Device 2</label></li>
</ul>
CSS
<style type="text/css">
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
/* 默认隐藏子项 */
#tree-menu ul {
display: none;
}
/* 点击节点展开子项 */
#tree-menu li.collapsed>ul {
display: block;
}
</style>
CSS
<style type="text/css">
#tree-menu li ul {
padding: 0.5rem 1rem;
}
</style>
CSS
<style type="text/css">
#tree-menu li ul {
padding: 0.5rem 1rem;
}
#tree-menu li {
border: 1px solid #ddd;
}
// 第一个子节点之后所有兄弟节点
#tree-menu li+li {
border-top: 0;
}
#tree-menu label {
display: block;
padding: 0.5rem 1rem;
}
#tree-menu label:hover {
background-color: aliceblue;
}
</style>
CSS
<style type="text/css">
#tree-menu li ul {
padding: 0.5rem 1rem;
}
#tree-menu li {
border: 1px solid #ddd;
border-radius: 10px;
margin-bottom:0.5rem;
}
/* #tree-menu li+li {
border-top: 0;
} */
#tree-menu label {
display: block;
padding: 0.5rem 1rem;
}
#tree-menu label:hover {
background-color: aliceblue;
border-radius: 10px;
}
</style>
li label{ }
这个示例表示:li元素下面所有层级的label
li>label{ }这个示例表示:li元素孩子级层级的label
CSS
#tree-menu li ul {
padding: 0.5rem 1rem;
}
#tree-menu li {
border: 1px solid #ddd;
/* border-radius: 10px;
margin-bottom:0.5rem; */
}
/* 第一个子节点之后的所有兄弟节点 */
#tree-menu li+li {
border-top: 0;
}
/* 第一个子节点 设置顶部圆角 */
#tree-menu li:first-child,
#tree-menu li:first-child>label {
border-radius: 10px 10px 0 0;
}
/* 最后一个子节点 设置底部圆角 */
#tree-menu li:last-child,
#tree-menu li:last-child>label {
border-radius: 0 0 10px 10px ;
}
/* 只有唯一 一个子节点时,顶部底部都设置圆角 */
#tree-menu li:only-child,
#tree-menu li:only-child>label {
border-radius: 10px ;
}
/*
展开时背景圆角修复
:first-child 第一个子节点
:not(:only-child)非唯一子节点
这里表示这个子节点有子项
*/
#tree-menu li.collapsed:first-child:not(:only-child)>label {
border-radius: 10px 10px 0 0;
}
#tree-menu li.collapsed:not(:only-child)>label {
border-radius: 0;
}
#tree-menu label {
display: block;
padding: 0.5rem 1rem;
}
/*
:hover 鼠标在元素上面时
*/
#tree-menu label:hover {
background-color: aliceblue;
/* border-radius: 10px; */
}
CSS
#tree-menu li label {
position: relative;
padding: 0.5rem 1rem 0.5rem 1.5rem;
}
/**
如果有子项,添加展开或折叠的标记符号。
默认折叠标记
*/
#tree-menu li label::before {
position: absolute;
content: '-';
left: 0;
width: 1.6rem;
height: 1.2rem;
text-align: center;
line-height: 1.2rem;
color: #333;
}
/**
:only-child表示没有兄弟元素
不显示标记
*/
#tree-menu li label:only-child::before {
content: ' ';
}
/* 显示展开标记 */
#tree-menu li.collapsed>label::before {
content: '+';
}
到此,一个还比较美观的树形菜单,基本完成了。
但是,有朋友说,我要实现以下需求呢?
1、不要边框;
2、保留缩进;
3、保留展开折叠标记;
4、横向拉通选择;
CSS
#tree-menu label {
position: relative;
display: block;
padding: 0.5rem 1rem;
}
#tree-menu label:hover {
background-color: aliceblue;
}
/** 缩进拉通选择*/
#tree-menu li label {
padding-left: 0;
}
#tree-menu li li label {
padding-left: 0.5rem;
}
#tree-menu li li li label {
padding-left: 1rem;
}
#tree-menu li li li li label {
padding-left: 1.5rem;
}
#tree-menu li li li li li label {
padding-left: 2rem;
}
#tree-menu li li li li li li label {
padding-left: 2.5rem;
}
/**
如果有子项,添加展开或折叠的标记符号。
默认折叠标记
*/
#tree-menu li label::before {
float: left;
content: '-';
width: 1.6rem;
height: 1.2rem;
text-align: center;
line-height: 1.2rem;
color: #333;
}
/**
:only-child表示没有兄弟元素
不显示标记
*/
#tree-menu li label:only-child::before {
content: ' ';
}
/* 显示展开标记 */
#tree-menu li.collapsed>label::before {
content: '+';
}
如果层级很深,我不是得写很多个li才能实现多级缩进?
比如:tree-menu li li li li li li li li li li li label{}
查找所有 label 元素,然后看 label 元素上面有多少个 li 元素,以此判断所属层级。
CSS
<script>
function parents(element, selector) {
var parentsArray = [];
var parent = element.parentNode;
while (parent && parent !== document) {
if (parent.matches(selector)) {
parentsArray.push(parent);
}
parent = parent.parentNode;
}
return parentsArray;
}
const items = document.querySelectorAll('#tree-menu label');
items.forEach((item) => {
const level = parents(item.parentElement, 'li').length
const padding = 10 * level;
item.style.paddingLeft = `${padding}px`;
});
</script>
1、我不想写JavaScript;
2、我不想写多个li li li li li li li;
3、我不想写多个.level1{} .level2{} .level3{};
4、我想写少量CSS代码,来解决这个问题,一劳永逸;
5、我想它支持无限层级的缩进;
有这样CSS代码吗?我怎么不知道?
你别说,还真有这样得CSS代码。
当然,这也是本文得重点,算一个CSS得小技巧吧。
CSS 函数 counters() 是一个嵌套计数器,返回表示指定计数器当前值的连接字符串。counters() 函数有两种形式: counters(name, string) 或 counters(name, string, style) 。它通常和伪元素搭配使用,但是理论上可以在支持<string>值的任何地方使用。生成的文本是具有给定名称的所有计数器的值,从最外层到最内层,之间由指定字符串分隔。计数器以指示的样式呈现,如果未指定样式,则默认为十进制。
先看一个例子:
HTML
<ol>
<li>
<ol>
<li></li>
<li></li>
<li></li>
</ol>
</li>
<li></li>
<li></li>
<li>
<ol>
<li></li>
<li>
<ol>
<li></li>
<li></li>
<li></li>
</ol>
</li>
</ol>
</li>
</ol>
CSS
ol {
counter-reset: listCounter;
}
li {
counter-increment: listCounter;
}
li::marker {
content: counters(listCounter, '.', upper-roman) ') ';
}
li::before {
content: counters(listCounter, ".") " == " counters(listCounter, ".", lower-roman) ;
}
通过上面的例子,我们看到了类似word的多级列表。此时很多朋友可能已经有思路了,那么我们将利用CSS这个特性,来实现上面的要求。
修改了部分样式
#tree-menu label {
position: relative;
display: block;
/* padding: 0.5rem 1rem; */
padding: 0.5rem 1rem 0.5rem 0;
}
/* #tree-menu li label::before {} */
#tree-menu li label::after {}
/* #tree-menu li label:only-child::before {} */
#tree-menu li label:only-child::after {}
/* #tree-menu li.collapsed>label::before {} */
#tree-menu li.collapsed>label::after {}
counters属性样式
/** 缩进拉通选择 修改前*/
/* #tree-menu li label {
padding-left: 0;
}
#tree-menu li li label {
padding-left: 0.5rem;
}
#tree-menu li li li label {
padding-left: 1rem;
}
#tree-menu li li li li label {
padding-left: 1.5rem;
}
#tree-menu li li li li li label {
padding-left: 2rem;
}
#tree-menu li li li li li li label {
padding-left: 2.5rem;
} */
/* 修改后 */
#tree-menu,
#tree-menu ul {
counter-reset: listCounter;
}
#tree-menu label {
counter-increment: listCounter;
}
#tree-menu label::before {
float: left;
/* 把标记设置成透明 */
color:transparent;
/* 默认数字*/
content: counters(listCounter, "");
}
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
/**
折叠状态与展开状态样的样式
*/
#tree-menu ul {
display: none;
}
#tree-menu li.collapsed>ul {
display: block;
}
#tree-menu label {
position: relative;
display: block;
padding: 0.5rem 1rem 0.5rem 0;
}
#tree-menu label:hover {
background-color: aliceblue;
}
/** 缩进拉通选择*/
/* 修改后 */
#tree-menu,
#tree-menu ul {
counter-reset: listCounter;
}
#tree-menu label {
counter-increment: listCounter;
}
#tree-menu label::before {
float: left;
/* 将序号设置为透明 */
color:transparent;
/***/
content: counters(listCounter, "");
}
/**
如果有子项,添加展开或折叠的标记符号。
默认折叠标记
*/
#tree-menu li label::after {
float: left;
content: '-';
width: 1.6rem;
height: 1.2rem;
text-align: center;
line-height: 1.2rem;
color: #333;
}
/**
:only-child表示没有兄弟元素
不显示标记
*/
#tree-menu li label:only-child::after {
content: ' ';
}
/* 显示展开标记 */
#tree-menu li.collapsed>label::after {
content: '+';
}
通过树形级联菜单,学习CSS选择器与CSS技巧,是一种非常有效的学习方法。我们不仅可以学会如何使用各种选择器,来控制页面元素,还能掌握一些实用的CSS技巧和概念。希望本文对您了解树形级联菜单、CSS选择器和CSS技巧有所帮助,并能为您在Web前端开发中的工作提供一些启发。
希望本文能够对您有所帮助,感谢您的阅读!
人人为我,我为人人,谢谢您的浏览,我们一起加油吧。
1、Web页面中的树形菜单的功能实现
利用树形菜单可以实现层次化的命令集,方便导航用户的操作。目前在 Web页面中可以采用许多不同的技术实现树形菜单的应用效果——如基于Ajax技术实现Web树状菜单、采用XML+JavaScript脚本创建树形菜单或者利用CSS(Cascading Style Sheets,层叠样式表)实现静态效果的树形菜单等。
DHTMLXTree是Web开发中运用较多的一个开源的树型菜单控件,允许开发人员快速开发Web界面中的树形菜单,它基于Ajax的JavaScript脚本库,允许在线编辑、拖拽、三种状态(全选、不选、半选)、复选框等模式。在加载大数据量的时候,仍然可以保持非常高效的速度。
DHTMLXTree本质上其实是一个在Web页面上实现树状显示效果的JavaScript控件,因此应用它不仅可以实现树型菜单,也可以实现树型目录等"树"状结构的数据显示效果。如下示图为应用DHTMLXTree控件实现的一个树形结构的数据显示效果的应用示例局部截图。
而如下示图为DHTMLXTree官方网站页面提供的有关技术文档局部截图,读者可以根据待开发的软件应用系统项目的需要下载相关的系统库文件和在线浏览技术参考文档资料。
在示例项目银行账户信息管理系统的后台页面的设计和实现中,也采用了DHTMLXTree树型控件实现应用系统中的后台管理功能的树形菜单,请见下图所示页面效果局部截图。
2、Web页面数据的分页显示功能实现
由于在软件应用系统中某个功能的页面需要显示大量的数据,为了方便应用系统的操作者对数据的快速浏览,应该要对待显示的目标数据进行分页显示。Web应用系统中数据分页显示技术也是Web表示层开发中比较通用的功能实现要求——所谓的数据分页显示功能要求,也就是将从软件应用系统后台数据库表中获得的各种结果数据人为地分成特定长度的数据块、并在Web页面中只显示其中某一块的数据,并为操作者提供继续浏览其它块数据的链接或者按钮(包括前、后页、第一和最后页、快速定位某页等方式)。
下图所示为示例项目银行账户信息管理系统中对用户账户信息进行数据分页显示的效果的局部截图,该分页实现技术是每次只向数据库系统请求页面大小的数据,大大地提高了每次前/后翻页时的查询速度。
当然,在具体实现时一定要达到将软件应用系统的表示层数据显示与数据的业务逻辑处理相互分离的设计和开发实现的基本目标。
3、解决Web表单重复提交的问题以保证数据的唯一性
由于各个Web浏览器都提供有【刷新】功能菜单——请见下图所示,为了防止操作者点击【刷新】功能菜单而造成对软件应用系统后台的多次重复请求,在软件应用系统的表示层开发中应该要避免产生表单重复提交的问题。
对于解决表单重复提交的技术问题,许多基于MVC体系架构的应用框架都提供了对应的技术支持和具体的实现方法。早期的Struts框架是通过提供Token(令牌)机制很好地解决了表单重复提交的问题——其基本的实现原理是:
Struts框架的服务器端程Action类程序在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配;而在处理完该次请求后,并且在将响应发送给客户端浏览器之前,将会产生一个新的令牌(一个随机的字符串),该令牌除传给客户端浏览器以外,也会将用户Session会话中保存的旧的令牌进行替换。
此时如果用户回退到刚才的提交页面并再次重复地提交请求时,客户端Web浏览器再次传递过来的令牌字符串就和服务器端保存的令牌字符串内容也就不一致,从而有效地防止了Web表单重复提交的发生。
而在Struts2应用框架中利用系统内带的<s:token />标签产生一个GUID(Globally Unique Identifier,全局唯一标识符)字符串值的隐藏输入框,同时还将GUID字符串放到Session会话中;在执行某个Web请求之前,Struts2应用框架中的缺省的"token"拦截器将会话中的令牌字符串与此时的Web请求令牌字符串比较,如果两者相同,则将会话中的令牌字符串删除并继续往下执行,否则向actionErrors程序类加入相关的错误信息。
如此一来,如果用户通过某种手段提交了两次相同的请求,两个令牌字符串就会不同。从而也有效地防止了Web表单重复提交的发生。
在示例项目银行账户信息管理系统中为了不依赖于Struts2等MVC框架系统,没有简单地采用这些MVC应用框架系统对Web表单重复提交的功能实现的技术支持。而是采用Web页面表单中的图形验证码进行限制,同样也能够达到相同的应用效果。
由于图形验证码在每次不同的Web请求时都会产生不同的值,从而控制重复提交的行为产生。在示例项目中的"开户"功能成功后,用户如果再次点击Web浏览器中的"回退"按钮后,将回到原来的Web表单请求页面。但此时Web页面表单中的验证码已经不一致,请见下图所示的功能操作状态图示,此时提交后,软件应用系统后台的验证码验证程序将报告错误而终止重复的Web请求。
但如果用户在Web表单中输入正确的验证码后再发送本次请求,软件应用系统后台将通过业务数据中的逻辑性和数据的一致性加以限制,而避免在物理数据库系统的数据库表中出现完全一样的两条记录数据。
4、Web表单中的数据有效性验证
软件应用系统的操作者可能由于操作的失误或者恶意的攻击或者无意识的错误数据输入等行为,在Web页面表单中将产生错误的输入数据。为了保证在软件应用系统后台能够正确地获得所需要的目标数据,应该要对Web表单中的各种关键性的输入数据进行数据验证(数据有效性验证)。
对于Web表单中提交的数据不仅需要应用Web客户端的数据验证(一般是采用JavaScript脚本语言实现),更应该要应用Web服务器端数据验证技术以真正达到软件应用系统的数据安全性、正确性和有效性等应用的要求。
这主要是由于目前有许多浏览器能够禁止执行Web客户端页面中所内嵌的JavaScript脚本语言程序代码而导致Web客户端的数据验证功能失效、或者恶意的攻击者直接通过Web客户端应用程序请求访问软件应用系统中的后台Web服务器端相关程序。下图所示为FireFox浏览器对Web页面中的JavaScript脚本语言的控制项目的局部截图。
在示例项目银行账户信息管理系统中应用Apache Validator验证器框架实现Web服务器端的数据验证,由于Apache Validator验证器框架是Jakarta的公共项目的一部分,读者可以从Apache Validator验证器官方网站中下载Validator框架的系统包文件。如下示图为Apache Validator验证器官方网站中技术特性介绍、系统库文件下载等信息页面局部截图。
下图所示为在示例项目银行账户信息管理系统中的AccountInfoManageAction类的checkVerifyCodeOK方法中应用Validator框架的代码片段局部截图。
5、统计软件应用系统的在线人数
Web应用系统的在线人数实时反映软件应用系统的访问状态,如果能够显示当前软件应用系统的在线人数,一方面能够让软件应用系统的管理人员及时地了解软件应用系统的当前负载情况,另一方面也让访问者了解到本软件应用系统的热门程度。
但要想实时准确地统计Web应用系统的在线人数,其实也是一件不太现实的事情。这是因为HTTP协议本身是无状态的协议,当Web客户端程序(一般为Web浏览器程序)向Web服务器发出一个Web请求时,Web服务器会马上建立一个新的TCP/IP连接(也就是会话Session);在该Web页面完全载入后,这个会话连接也就关闭了;另外,正是由于HTTP协议是无状态的,所以也就无法知道某个Web请求访问是否已经离开或者Web请求者已经关闭了Web浏览器。
因此,Web应用中所谓的在线人数其实应该是指在"一定时间段内"同时访问Web站点的人数,而不是基于HTTP协议的并发连接数。但这个"一定时间段内"对于不同的Web服务器也是有差别的,如Tomcat服务器默认的Session会话超时为30分钟(但一般的Web网站都采用15分种的时间标准)。
在示例项目银行账户信息管理系统中也提供了该功能的具体实现,是利用实现HttpSessionListener接口的Web监听器统计在线Session个数、并将Tomcat服务器默认的Session会话超时时间改变为15分钟,最后在Web页面中显示输出本软件应用系统的在线人数。本示例项目最后实现的效果局部截图如图所示。
6、在软件应用系统中实现文件上传功能
文件上传或者下载也是Web应用系统中需要提供的功能,在示例项目银行账户信息管理系统中利用Apache Commons-FileUpload组件实现文件的上传功能,该FileUpload组件可以实现每次上传一个或多个文件,并可限制文件大小——比如在用户注册表单中允许注册者自行上传自己的图像文件,请见下图所示的局部截图。
7、在软件应用系统中实现文件下载功能
在Web应用系统的开发实现中,大部分的文件下载都是直接通过建立下载文件的URL文件链接方式直接进行下载。但是考虑到在Web应用中的文件下载具体实现时的盗链、跨服务器下载访问等方面的因素,直接文件流下载的方式也是必要的。因为,此时Web应用系统能够对下载的文件以及下载的操作者进行更多方面的安全及身份验证的检查和控制。
在Struts2应用框架中实现数据流下载时只需要改变Struts2应用框架中的result Type为Stream类型即可以实现本功能要求——请见下面的代码示例所示的某个实现文件下载功能的DownLoadFileAction的配置定义示例内容中的黑体标识的内容。如下为某个实现文件下载功能的DownLoadFileAction的配置定义示例
<action name="oneDownLoadGIFFile"
class="com.px1987.struts2.action.DownLoadFileAction">
<param name="inputPath">/downImages/logo.gif</param>
<result name="success" type="stream">
<param name="contentType">image/gif</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">filename="logo.gif"</param>
<param name="bufferSize">4096</param>
</result>
</action>
在示例项目银行账户信息管理系统中采用在Servlet程序中直接控制文件输出流的方式实现文件下载的控制。具体的功能实现代码请见如下所附的代码示例,该doDownLoadFile方法作为某个J2EE Servlet程序中一个功能方法被doGet方法所调用,并请注意其中的黑体部分的语句代码——实现文件下载功能的代码示例
public void doDownLoadFile(HttpServletRequest request, String downFileName,
HttpServletResponse response, String downFilePath)
throws ServletException, IOException{
ServletOutputStream servletOutputStream = null;
FileInputStream fileInputStream = null;
BufferedInputStream bufferedInputStream =null;
File downLoadTargetFile = new File(downFilePath+"/"+downFileName);
if(!downLoadTargetFile.exists()){
response.sendError(404,"没有找到要下载的目标文件!");
return;
}
try {
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment; filename=\"" + downFileName + "\"");
servletOutputStream = response.getOutputStream(); fileInputStream = new java.io.FileInputStream(downFilePath +
"\\"+ downFileName);
bufferedInputStream = new BufferedInputStream(fileInputStream);
byte[] oneBuffer = new byte[10240];
int byteNumber;
while ((byteNumber=bufferedInputStream.read(oneBuffer)) != -1){
servletOutputStream.write(oneBuffer,0,byteNumber);
}
}
catch (FileNotFoundException e) {
}
catch (IOException e) {
}
finally {
if(bufferedInputStream != null){
bufferedInputStream.close();
}
if(servletOutputStream != null){
servletOutputStream.close();
}
}
}
其中的response.setContentType("application/octet-stream");语句主要是设置Http响应头和要下载保存的文件名,Web浏览器将根据开发人员在Http数据流的Head部分的MIME(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)头的设置内容"application/octet-stream"直接产生出文件下载的对话框提示、并且按照设置的内容采用二进制数据格式传输文件流数据。
*请认真填写需求信息,我们会在24小时内与您取得联系。