IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 【EL】【JSTL】【文件上传&下载】【学习笔记】寒假javaweb学习之旅1.5 -> 正文阅读

[JavaScript知识库]【EL】【JSTL】【文件上传&下载】【学习笔记】寒假javaweb学习之旅1.5

厦工我的厦工😭😭😭😭😭😭😭😭,daisuki😍😍😍😍😍😍😍😍,寒假你别走😭😭😭😭😭😭😭😭

EL表达式

EL表达式的全称 : Expression Language 是表达式语言
EL表达式作用 ????: EL表达式主要是代替jsp页面中的表达式脚本在jsp页面中进行数据的输出

格式 : ${表达式}??????????(嗨呀怎么和Jquery这么像捏🤗)

1、EL表达式初入

1.1、EL表达式优势

因为EL表达式在输出数据的时候,要比jsp的表达式脚本要简洁很多😍😍,下面举例,输出页面中的数据

在这里插入图片描述

而且当输出不存在的值的时候,EL表达式不会出现null,下图,我们试试输出不存在的值

在这里插入图片描述

1.2、EL表达式搜索四个域数据的顺序

结论 : 生命周期短的域,先被搜索

证明

在前面的jsp,我们说过了四个域,分别是pageContext、request、session、application,其生命周期长短,从左到右,依次升高,那么如果,我这样写

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>这里是a.jsp</title>
</head>
<body>
  <%
     request.setAttribute("key","request");
     session.setAttribute("key","session");
     application.setAttribute("key","application");
     //我们故意把生命周期短的放到最底下,证明这不是代码顺序问题
      pageContext.setAttribute("key","pageContext");
  %>
    ${key}
</body>
</html>

这时从浏览器,取key,会是谁呢?🤔🤔🤔

在这里插入图片描述

是生命周期最短的pageContext捏😁,因此,我们这里证明了, 生命周期短的域,先被搜索

1.3、输出复杂的bean对象

先写个javaBean把,这里写个Person类

public class Person {
    private String name;
    private String[] phones;
    private List<String> cities;
    private Map<String,Object> map;
// construct、get、set、toString重写 省略

这时候我们写个EL表达式去取值

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>这是是c.jsp</title>
</head>
<body>
    <%
        Person person = new Person();
        person.setName("哈哈哈");
        person.setPhones(new String[]{"12345","123456","2233"});
        List<String> cities = new ArrayList<String>();
        cities.add("a市");
        cities.add("b市");
        cities.add("c市");
        person.setCities(cities);
        Map<String, Object> map = new HashMap<>();
        map.put("k1","v1");
        map.put("k2","v2");
        map.put("k3","v3");
        person.setMap(map);
        pageContext.setAttribute("p",person);
    %>
    person的全部属性是 : ${p} <br>
    person的name是: ${p.name} <br>
    person的phone是: ${p.phones} <br>
    person的phone[1]: ${p.phones[1]} <br>
    person的cities是: ${p.cities} <br>
    person的cities[1]: ${p.cities[1]} <br>
    person的map是 : ${p.map} <br>
    person的k1对应的值是 : ${p.map.k1} <br>
</body>
</html>

在这里插入图片描述

结论 : EL表达式根据get方法来获取bean的属性值

证明 :

这里我们在Person类中,只写了getAge()方法,并没有写age字段

在这里插入图片描述

用EL表达式获取

person的age是: ${p.age}

下图,我们发现,可以正常的获取
在这里插入图片描述

1.4、EL表达式—运算

EL表达式支持运算,并输出结果

关系运算

关系运算符说明范例结果
== 或 eq等于${ 5 == 5}${ 5 eq 5}true
!= 或 ne不等于${5!=5}${5ne5}false
< 或 It小于${3<5}${3lt5}true
> 或 gt大于${2>10}${2gt10}false
<= 或 le小于等于${5<=12}${5le 12}true
>= 或 ge大于等于${3>=5}${3ge5}false

逻辑运算

逻辑运算符说明范例结果
&& 或 and与运算符${12==12 && 12<11 }${12 ==12 and 12 <11 }false
|| 或 or或运算${12==12||12<11}${12==12or12<11}true
! 或 not取反运算${!true}${not true}false

算数运算

算数运算符说明范例结果
+加法${12 + 18}30
-减法${18 - 8}10
*乘法${12 * 12}144
/ 或 div除法${ 144 / 12}${144 div 12}12
% 或 mod取模${144 % 10}${144 mod 10}4

empty运算

empty运算可以判断一个数据是否为空,如果为空,则输出true,不为空输出false 。

以下几种情况为空:
1、值为null值的时候,为空
2、值为空串的时候,为空
3、值是Object类型数组,长度为零的时候
4、list集合,元素个数为零
5、map 集合,元素个数为零

🔬证明 :

在这里插入图片描述

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>这里是e.jsp</title>
</head>
<body>
    <%
//        1、值为null值的时候,为空
        request.setAttribute("emptyNull",null);
//        2、值为空串的时候,为空
        request.setAttribute("emptyStr","");
//        3、值是Object类型数组,长度为零的时候
        request.setAttribute("emptyObject",new Object[]{});
//        4、list集合,元素个数为零
        ArrayList<Object> list = new ArrayList<>();
        request.setAttribute("emptyList",list);
//        5、map 集合,元素个数为零
        HashMap<Object, Object> map = new HashMap<>();
        request.setAttribute("emptyMap",map);
    %>
    ${empty emptyNull} <br>
    ${empty emptyStr} <br>
    ${empty emptyObject} <br>
    ${empty emptyList} <br>
    ${empty emptyMap} <br>
</body>
</html>

三元运算

表达式1? 表达式2 : 表达式3
如果表达式1的值为真,返回表达式2的值,如果表达式1的值为假,返回表达式3的值。

. 和 [ ]

点运算,可以输出Bean对象中某个属性的值。
[]中括号运算,可以输出有序集合中某个元素的值。

并且[]中括号运算,还可以输出map集合中key里含有特殊字符的key的值。

map.put("a.a.a","aaa");

比如,如果我们这样取,会非常麻😨

$(map.a.a.a)		这样写是错误的
$(map['a.a.a'])		正确写法,' '或" "包起来

2、EL表达式11个隐藏对象

EL个达式中11个隐含对象,是EL表达式中自己定义的,可以直接使用

变量类型作用
pageContextPageContextlmpl它可以获取jsp 中的九大内置对象
pageScopeMap<String,Object>它可以获取pageContext域中的数据
requestScopeMap<String,Object>它可以获取Request域中的数据
sessionScopeMap<String,Object>它可以获取Session域中的数据
applicationScopeMap<String,Object>它可以获取ServletContext域中的数据
paramMap<String,String>它可以获取请求参数的值
paramValuesMap<String,String[]>它也可以获取请求参数的值,获取多个值的时候使用。
headerMap<String,String>它可以获取请求头的信息
headerValuesMap<String,String[]>它可以获取请求头的信息,它可以获取多个值的情况
cookieMap<String,Cookie>它可以获取当前请求的Cookie 信息
initParamMap<String,String>它可以获取在web.xml中配置的< context-param >上下文参数

2.1、获取四个域的属性

在这里插入图片描述

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>这里是f.jsp</title>
</head>
<body>
    <%
        pageContext.setAttribute("key","pageContext");
        request.setAttribute("key","request");
        session.setAttribute("key","session");
        application.setAttribute("key","application");
    %>
    我们需要输出pageContext的key ${pageScope.key} <br>
    我们需要输出request的key ${requestScope.key} <br>
    我们需要输出session的key ${sessionScope.key} <br>
    我们需要输出application的key ${applicationScope.key} <br>
</body>
</html>

2.2、pageContext

它可以获取jsp中的九大内置对象

常用来

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>这里用来测试pageContext</title>
</head>
<body>
    1.协议: ${pageContext.request.scheme} <br>
    2.服务器ip: ${pageContext.request.serverName} <br>
    3.服务器端口: ${pageContext.request.serverPort} <br>
    4.获取工程路径:   ${pageContext.request.contextPath} <br>
    5.获取请求方法:   ${pageContext.request.method} <br>
    6.获取客户端ip地址: ${pageContext.request.remoteHost} <br>
    7.获取会话的id编号: ${pageContext.session.id} <br>
</body>
</html>

在这里插入图片描述

你甚至可以这写,来使代码方便

<%
	pageContext.setAttribute("req",request);
%>
1.协议: ${req.scheme} <br>

2.3、剩下6个隐藏对象

param 和 paramValues

它可以获取请求参数的值

输出请求username ${param.username} <br>
输出请求password ${param.password} <br>
paramValues数组 ${paramValues} <br>
用paramValues输出请求username ${paramValues.username[0]} <br>
用paramValues输出请求password ${paramValues.password[0]} <br>
用paramValues输出hobby1 ${paramValues.hobby[0]} <br>
用paramValues输出hobby2 ${paramValues.hobby[1]} <br>

在这里插入图片描述

header 和 headerValues

它可以获取请求头的信息

header输出请求头【User-Agent】的值 ${header['User-Agent']}<br>
header输出请求头【Connection】的值 ${header['Connection']}<br>
headerValues输出请求头【User-Agent】的值 ${headerValues['User-Agent'][0]}<br>

在这里插入图片描述

cookie

它可以获取当前请求的Cookie信息

cookie ${cookie}    <br>
cookie对象 ${cookie.JSESSIONID} <br>
cookie对象名称 ${cookie.JSESSIONID.name} <br>
cookie对象值 ${cookie.JSESSIONID.value} <br>

在这里插入图片描述

initParam

它可以获取在web.xml中配置的< context-param >上下文参数

先去xml下写配置文件

<context-param>
    <param-name>username</param-name>
    <param-value>root</param-value>
</context-param>
<context-param>
    <param-name>url</param-name>
    <param-value>jdbc:mysql://localhost:3306</param-value>
</context-param>

在这里插入图片描述

JSTL

1、JSTL初入

1.1、JSTL介绍

JSTL标签库全称是指JSP Standard Tag Library ( JSP标准标签库),是一个不断完善的开放源代码的JSP标签库

EL表达式主要是为了替换jsp中的表达式脚本,而标签库则是为了替换代码脚本。这样使得整个jsp页面变得更佳简洁

1.2、JSTL的5个标签库

功能范围URI前缀
核心标签库–重点http://java.sun.com/jsp/jst/corec
格式化http://java.sun.com/jsp/jst/fmtfmt
函数http://java.sun.com/jsp/jstl/functionsfn
数据库(不使用)http://java.sun.com/jsp/jst/sq1sql
XML(不使用)http://java.sun.com/jsp/jstl/xmlx

在jsp标签中使用taglib指令引入标签库

CORE 标签库
<%@ taglib prefix="c" uri= "http://java. sun. com/jsp/jstl/core" %>
XML标签库
<%@ taglib prefix="x" uri= "http://java. sun. com/jsp/jstl/xmL" %>
FMT标签库
<%@ taglib prefix= "fmt" uri= "http://java. sun. com/jsp/jstl/fmt" %>
SQL标签库
<%@ taglib prefix="sqL" uri= "http://java. sun. com/jsp/jstl/sqL" %>
FUNCTIONS标签库
<%@ taglib prefix= "fn" uri="http://java. sun. com/jsp/jstl/functions" %>

1.3、JSTL标签库使用步骤

1、先导入JSTL标签库的jar包

在这里插入图片描述

2、第二步,使用taglib指令引入标签库,🤤🤤🤤🤤,下面引入的是核心库

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

2、Core核心库

2.1、<c:set>

作用 : set标签可以往域中保存数据

格式 :

<c:set scope=" "   var =" " value=" " /></c:set>

scope属性 表示放到哪个域 page(PageContext域) 、request(Request域) 、session(Session域)、application(ServletContext域)

var属性 设置key是多少

value属性 设置值时多少

实践

在这里插入图片描述

保存之前: ${requestScope.abc} <br>
<c:set scope="request" var="abc" value="123"></c:set>
保存之后: ${requestScope.abc} <br>

2.2、<c:if>

作用 : 来做if判断

格式 :

<c:if text="">执行的内容</c:if>

text属性 表示判断的条件,里面写EL表达式

实践

在这里插入图片描述

<c:if test="${12 == 12}">
    <h1>12等于12</h1>
</c:if>
<c:if test="${12 != 12}">
    <h1>12不等于12</h1>
</c:if>

2.3、<c:choose><c:when><c:otherwise>

作用 : 多路判断。跟switch … case … default非常接近
而且不需要手动break😁

格式 :

<c:choose>
    <c:when test=" ">
    	执行你想要的内容1
    </c:when>
    <c:when test=" ">
        执行你想要的内容2
    </c:when>
    <c:otherwise>
    	执行你想要的内容3
    </c:otherwise>
</c:choose>

chose标签 表示开始选择判断

when标签 表示每一种情况判断

otherwise标签 表示剩下的情况

实践

在这里插入图片描述

<c:choose>
    <c:when test="${requestScope.age > 100}">
        你真老
    </c:when>
    <c:when test="${requestScope.age < 100 && requestScope.age > 90}">
        再活10年才算老
    </c:when>
    <c:otherwise>
        你真年轻
    </c:otherwise>
</c:choose>

注意点

1、标签里不能使用html注释,要使用jsp注释

在这里插入图片描述

2、when标签的父标签一定要是choose 标签

在这里插入图片描述

所以我们要在它的外面,加上一层choose

在这里插入图片描述

2.4、<c:forEach>

作用 : 遍历用的,不难看出🤔🤔

格式

<c:forEach begin="" end="" var=""></c:forEach>

begin属性 设置开始的索引
end属性 设置结束的索引
var属性 表示循环的变量(也是当前正在遍历到的数据)

<c:forEach begin="1" end="10" var="i"></c:forEach>
//类似于 
for(int i = 1 ; i <= 10 ; i++)

实践

遍历输出1~10

在这里插入图片描述

<table border="1">
    <c:forEach begin="1" end="10" var="i">
        <tr>
            <td>第${i}</td>
        </tr>
    </c:forEach>
</table>

3、<c:forEach>深入

3.1、遍历Object数组

格式 :

<c:forEach items="" var="" ></c:forEach>

items表示遍历的数据源(遍历的集合)
var表示当前遍历到的数据

<c:forEach items="${requestScope.arr}" var="item">
//类似
for(Object item: arr)

实践

在这里插入图片描述

<%
request.setAttribute("arr",new String[]{"123","456","789"});
%>
<c:forEach items="${requestScope.arr}" var="item">
    ${item}
</c:forEach>

3.2、遍历Map集合

格式 :

<c:forEach items="" var="" ></c:forEach>

items表示遍历的数据源(遍历的集合)
var表示当前遍历到的数据

java里,我们是这样遍历Map的

for(Map.Entry<String,Object> entry : map.entrySet()){
}

实践

在这里插入图片描述

<%
HashMap<String, Object> map = new HashMap<>();
map.put("k1","v1");
map.put("k2","v2");
map.put("k3","v3");
request.setAttribute("map",map);
%>
<c:forEach items="${requestScope.map}" var="entry">
    输出entry: ${entry} <br>
    输出entry的key: ${entry.key} <br>
    输出entry的value: ${entry.value} <br>
</c:forEach>

3.3、遍历List集合

格式 :

<c:forEach items="" var="" ></c:forEach>

items表示遍历的数据源(遍历的集合)
var表示当前遍历到的数据

遍历List集合,list中存放Student类,有属性:编号,用户名,密码,年龄

在这里插入图片描述

public class Student {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
 	//construct、get、set、toString 省略   
}
<%
        ArrayList<Student> students = new ArrayList<>();
        for(int i = 1 ; i <= 10 ; i++){
            students.add(new Student(i,"student"+i,"pwd"+i,18+i))
        }
        request.setAttribute("students",students);
    %>
    <table border="1">
        <tr>
            <td>学号</td>
            <td>用户名</td>
            <td>密码</td>
            <td>年龄</td>
            <td>操作</td>
        </tr>
        <c:forEach items="${requestScope.students}" var="student">
            <td>${student.id}</td>
            <td>${student.username}</td>
            <td>${student.password}</td>
            <td>${student.age}</td>
            <td>修改,删除</td>
        </c:forEach>
    </table>

3.4、forEarch所有属性详细介绍

<c:forEarch begin="" end="" step="" varStatus="" items="" var=""></c:forEarch>

items表示遍历的集合
var表示遍历到的数据
begin表示遍历的开始索引值
end表示结束的索引值

上面这些前面都有,那我们说说下面的😁😁😁

step属性

表示遍历的步长值

比如这里的,for(inti=1;i<10;i+=2),i+=2

varStatus属性表示当前遍历到的数据的状态

我们会发现varStatus是一个对象,还是一个内部类

在这里插入图片描述

然后我们再去找找他的位置在javax.servlet.jsp.jstl.core.LoopTagSupport找找看
在这里插入图片描述

发现他实现了LoopTagStatus类,那我们就去LoopTagStatus类康康把😍😍😍,下图是在LoopTagStatus接口的总结
在这里插入图片描述

实践

在这里插入图片描述

    <%
        ArrayList<Student> students = new ArrayList<>();
        for(int i = 1 ; i <= 10 ; i++){
            students.add(new Student(i,"student"+i,"pwd"+i,18+i));
        }
        request.setAttribute("students",students);
    %>
    <table border="1">
        <tr>
            <td>getCurrent()</td>
            <td>getIndex()</td>
            <td>getCount()</td>
            <td>isFirst()</td>
            <td>isLast()</td>
            <td>getBegin()</td>
            <td>getEnd()</td>
            <td>getStep()</td>
        </tr>
        <c:forEach begin="3" end="8" step="2" varStatus="status" items="${requestScope.students}" var="student">
            <tr>
                <td>${status.current}</td>
                <td>${status.index}</td>
                <td>${status.count}</td>
                <td>${status.first}</td>
                <td>${status.last}</td>
                <td>${status.begin}</td>
                <td>${status.end}</td>
                <td>${status.step}</td>
            </tr>
        </c:forEach>
    </table>

文件的上传和下载

文件的_上传和下载,是非常常见的功能。很多的系统中,或者软件中都经常使用文件的上传和下载。
比如: QQ头像,就使用了.上传。
邮箱中也有附件的上传和下载功能。
OA系统中审批有附件材料的上传。

1、文件上传

1.1、文件上传初入

1、要有一个form标签,method=post 请求
2、form标签的encType属性值必须为multipart/form-data值
3、在form标签中使用input type=file添加上传的文件
4、编写服务器代码接收,处理上传的数据。

<form action="uploadServlet" method="post" enctype="multipart/form-data">
    用户名: <input type="text" name="username"> <br/>
    头像: <input type="file" name="photo">
    <input type="submit" value="提交">
</form>
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("接收到上传的文件辣");
    }
}

在这里插入图片描述

1.2、文件上传的http协议内容

在这里插入图片描述

服务器接收数据

因为浏览器给我的发送的是,二进制流,所以我们需要用二进制流来读取

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("接收到上传的文件辣");
    ServletInputStream inputStream = request.getInputStream();
    byte[] buffer = new byte[102400];
    int read = inputStream.read(buffer);
    System.out.println(new String(buffer,0,read));
}

下图为,二进制流读取到的内容

在这里插入图片描述

1.3、解析上传数据

我们用😍commons-fileupload.jar 里面的常用API 😍 来解析上传数据

第一步,就是需要导入两个jar包

commons-fileupload.jar需要依赖commons-io.jar 这个包,所以两个包我们都要引入。

commons-fileupload-1.2.1 .jar

commons-io-1.4.jar

在这里插入图片描述

常用API

我们主要是用ServletFileUpload这个类来解析数据

ServletFileUpload类: 用于解析上传数据

Fileltem类: 每一个表单项

方法作用
boolean ServletFileUpload.isMultipartContent(HttpServletRequest request)判断当前上传的数据格式是否是多段的格式
public List<Fileltem> parseRequest(HttpServletRequest request)解析上传数据
boolean FileItem. isFormField()判断当前这个表单项,是否是普通的表单项。还是上传的文件类型true为普通类型的表单项,false为上传的文件类型
String FileItem.getF ieldName( )获取表单项的name属性值
String FileItem.getString()获取当前表单项的值
String FileItem.getName()获取上传的文件名
void FileItem.write( file )将上传的文件写到参数file所指向抽硬盘位置

fileupload类库的使用

在这里插入图片描述

public class UploadServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1、先判断上传的数据是否是多段数据(只有是多段数据,才是文件上传的)
        if(ServletFileUpload.isMultipartContent(request)){
            // 创建FileItemFactory实现类
            FileItemFactory fileItemFactory = new DiskFileItemFactory();
            // 创建一个用于解析上传数据的工具类ServletFileUpload类
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
            // 解析上传的数据,得到每一个表单项
            try {
                List<FileItem> list = servletFileUpload.parseRequest(request);
                // 循环判断,每一个表单项,是普通类型,还是上传文件
                for(FileItem fileItem : list){
                    if(fileItem.isFormField()){
                        // 普通表单项
                        System.out.println("表单项的name属性值: " + fileItem.getFieldName());
                        // 参数UTF-8 解决乱码问题
                        System.out.println("表单项的value属性值: " + fileItem.getString("UTF-8"));
                    }else{
                        // 上传文件
                        System.out.println("表单项的name属性值" + fileItem.getFieldName());
                        System.out.println("上传的文件名" + fileItem.getName());
                        fileItem.write(new File("d\\" +  fileItem.getName()));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2、文件下载

2.1、实现文件下载

图解

在这里插入图片描述

代码实现

在这里插入图片描述

public class DownLoadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        1、获取要下载的文件名
        String downLoadFileName = "p.jpg";
//        2、读取要下载的文件内容(通过ServletContext对象读取)
        ServletContext servletContext = getServletContext();
        // 获取下载的文件类型
        String mimeType = servletContext.getMimeType("/file/" + downLoadFileName);
        System.out.println("下载的文件类型为: " + mimeType);
//        4、在回传前,通过响应头,告诉客户端返回的数据类型
        response.setContentType(mimeType);
//        5、还要告诉客户端收到的 数据是用于下载使用(还是:使用响应头)
        // Content-Disposition 响应头,表示收到的数据怎么处理
        // attachment 表示附件,表示下载使用
        // filename= 表示指定下载的文件名
        response.setHeader("Content-Disposition","attachment;filename=" + downLoadFileName);

        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downLoadFileName);
        //  获取响应的输出流
        ServletOutputStream outputStream = response.getOutputStream();
//        3、把下载的文件内容回传 给客户端
        // 读取输入流中全部数据,复制给输出流,输出流给客户端
        IOUtils.copy(resourceAsStream,outputStream);
    }
}

2.2、中文乱码问题

谷歌浏览器和IE浏览器,我们可以用URLEncoder,解决下载的文件名是中文乱码的问题

// 下载的文件名是由响应头决定的
response.setHeader("Content-Disposition","attachment;filename=中文.jpg");

我们这么改之后,会出现下图的问题,我们去看看响应头,就会发现http协议不支持中文

在这里插入图片描述

下面我们这么修改,url编码是把汉字转为%xx%xx的格式

response.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode("中文.jpg","UTF-8"));

确实是中文,没有问题了,而且url编码确实是把汉字转为%xx%xx的格式

在这里插入图片描述

2.3、base64编码解决中文乱码

base64编码,可以解决火狐浏览器的附加中文名词问题

编码

public class Base64Test {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String context = "这是需要Base64编码的内容";
        // 创建一个Base64编辑器
        BASE64Encoder base64Encoder = new BASE64Encoder();
        // 执行Base64编码操作
        String encodeString = base64Encoder.encode(context.getBytes("UTF-8"));
        System.out.println(encodeString);       //输出内容为6L+Z5piv6ZyA6KaBQmFzZTY057yW56CB55qE5YaF5a65
    }
}

解码

这里,我们对上面得到的6L+Z5piv6ZyA6KaBQmFzZTY057yW56CB55qE5YaF5a65进行解码

public class Base64Test {
    public static void main(String[] args) throws Exception {
        // 创建一个Base64解码器
        BASE64Decoder base64Decoder = new BASE64Decoder();
        // 执行Base64解码操作
        byte[] buffer = base64Decoder.decodeBuffer("6L+Z5piv6ZyA6KaBQmFzZTY057yW56CB55qE5YaF5a65");
        String context = new String(buffer,"UTF-8");
        System.out.println(context);		// 输出 "这是需要Base64编码的内容"
    }
}

解决火狐浏览器问题

如果客户端浏览器是火狐浏览器。那么我们需 要对中文名进行BASE64的编码操作
这时候需要把请求头Content-Disposition: attachment;filename=中文名
编码成为: Content -Disposition:attachment; filename== ?charset?B?xxxxx?=

?

=?charset?B?xxxx?=说明
=?表示编码内容的开始
charset表示字符集
B表示BASE64编码
XXXX表示文件名BASE64编码后的内容
?=表示编码内容的结束
response.setHeader("Content-Disposition","attachment;filename==?UTF-8?B?"+new BASE64Encoder().encode("中文.jpg".getBytes("UTF-8")) +"?=" );

假装这是火狐浏览器(🐕

在这里插入图片描述

解决IE浏览器乱码问题

现在发现IE浏览器又出现乱码了,如下图,那么我们就结合刚刚所学内容,使用分支语句,来解决
在这里插入图片描述

if(request.getHeader("User-Agent").contains("Chrome")){
    response.setHeader("Content-Disposition", "attachment;filename==?UTF-8?B?" + new BASE64Encoder().encode("中文.jpg".getBytes("UTF-8")) + "?=");
} else{
    response.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode("中文.jpg","UTF-8"));
}

距离寒假结束还有9day

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-19 01:03:52  更:2022-02-19 01:05:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:27:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码