文件上传下载
1.文件上传
文件上传的应用
比如个人信息的管理,上传头像
比如商品信息的管理,上传商品的图片
这些都需要通过浏览器客户端将图片上传到服务器的磁盘上
2.文件上传原理
所谓的文件上传就是服务器端通过request对象获取输入流,将浏览器端上传的数据读取出来,保存到服务器端
客户端浏览器注意事项:
1.请求方式必须是 post
2.需要使用组件
3.表单必须设置enctype=“multipart/form-data”
服务器端处理通过request对象,获取InputStream, 可以将浏览器提交的所有数据读取到
3.上传开源框架-commons-upload
用来处理表单文件上传的一个开源组件( Commons-fileupload ),可以让开发人员轻松实现web文件上传功能,因此在web开发中实现文件上传功能,通常使用Commons-fileupload组件实现
使用Commons-fileupload组件实现文件上传,需要导入相应的jar包
4.文件上传案例–上传头像
在浏览器端创建一个可以上传头像的表单,在服务器端通过commons-fileupload完成文件上传
浏览器端注意三件事情:
1.表单的method=post
2.设置enctype=multipart/form-date
3.使用具有name属性的file元素
在服务器端
1.创建DiskFileItemFactory(ServletFileUpload工厂类)
2.创建ServletFileUpload(用于处理文件上传的类)
3.通过ServletFileUpload的parseRequest方法得到所有的FileItem
IOUtils:文件上传IO流类
BeanUtils:存储表单内文本信息类
设置乱码
upload.setHeaderEncoding(“UTF-8”);
项目搭建,导包,省略
实体类Student
package com.qf.pojo;
public class Student extends User{
private String hobbies;
//无参构造,有参构造,get,set,toString省略
}
实体类User
package com.qf.pojo;
public class User {
private String username;
private String password;
private String name;
private String sex;
private int age;
private String photo;
//无参构造,有参构造,get,set,toString省略
}
客户端 - 上传文件注意事项:
1.必须使用post请求
get请求的地址后面全是纯文本数据,而文件是二进制数据,大型文件有很多字符,地址框长度有限制,容纳不了
2.以二进制流的形式上传数据 – enctype=“multipart/form-data” 二进制流
3.使用文件组件上传 –
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>注册页面</h1>
<form action="RegisterServlet" method="post" enctype="multipart/form-data">
账号:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
姓名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
性别:
<input type="radio" name="sex" value="man" checked="checked"/>男
<input type="radio" name="sex" value="woman"/>女
<br/>
爱好:
<input type="checkbox" name="hobbies" value="football"/>足球
<input type="checkbox" name="hobbies" value="basketball"/>篮球
<input type="checkbox" name="hobbies" value="shop"/>购物
<br/>
上传头像:<input type="file" name="photo"><br>
<input type="submit" value="注册"/>
<input type="button" value="返回" οnclick="goWelcome()">
</form>
<script type="text/javascript">
function goWelcome(){
window.location = "http://localhost:8080/StudentManagementSystem_Web_exploded/";
}
</script>
</body>
</html>
4.1 基础方式
第一种:
使用了 enctype=“multipart/form-data”,正常传过来的数据是二进制流,使用输入输出流接收
缺点:太麻烦了,淘汰
package com.qf.servlet;
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletInputStream in = request.getInputStream();
StringBuffer sb = new StringBuffer();//接收对象
byte[] bs=new byte[1024];
int len;
while ((len=in.read(bs))!=-1){
sb.append(new String(bs,0,len));
}
//输出一下
System.out.println(sb.toString());
4.2 使用上传开源框架-commons-upload
使用上传开源框架-commons-upload,需要导包
RegisterServlet
处理二进制数据 – 利用传统IO的方式拷贝到本地磁盘
缺点:每次都要去拷贝文件,太麻烦了
package com.qf.servlet;
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建文件上传工厂类的对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传类的对象
ServletFileUpload upload = new ServletFileUpload(factory);
try {
//解析请求
List<FileItem> list = upload.parseRequest(request);//加泛型
//解析出来有文本数据(账号到爱好)和二进制数据(头像file)
for (FileItem fileItem : list) {
if (fileItem.isFormField()){//文本数据
String name = fileItem.getFieldName();
System.out.println("文本数据 -- " + name);
}else {//二进制数据
//拷贝
InputStream in = fileItem.getInputStream();
//放在D:\\text文件夹的xxx.jpg里
FileOutputStream out = new FileOutputStream("D:\\text\\xxx.jpg");
byte[] bs=new byte[1024];
int len;
while ((len=in.read(bs))!=-1){
out.write(bs,0,len);
}
in.close();
out.close();
}
}
} catch (FileUploadException e) {
throw new RuntimeException(e);
}
}
}
解析请求request
运行结果:
改进:
每次都要去拷贝文件,太麻烦了,用IOUtils直接拷贝(导包导进去的)
IOUtils:文件上传IO流类
处理二进制数据 – 利用IOUtils实现文件的拷贝
package com.qf.servlet;
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建文件上传工厂类的对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传类的对象
ServletFileUpload upload = new ServletFileUpload(factory);
try {
//解析请求
List<FileItem> list = upload.parseRequest(request);//加泛型
//解析出来有文本数据(账号到爱好)和二进制数据(头像file)
for (FileItem fileItem : list) {
if (fileItem.isFormField()){//文本数据
String name = fileItem.getFieldName();
System.out.println("文本数据 -- " + name);
}else {//二进制数据
//拷贝
InputStream in = fileItem.getInputStream();
//放在D:\\text文件夹的xxx.jpg里
FileOutputStream out = new FileOutputStream("D:\\text\\xxx.jpg");
//就是这句话,copy
IOUtils.copy(in,out);
in.close();
out.close();
}
}
} catch (FileUploadException e) {
throw new RuntimeException(e);
}
}
}
4.3 设置保存上传文件的服务器目录
使用IOUtils,每次上传的都是在D:\text\xxx.jpg里面,而且每次都会替换、覆盖xxx.jpg
处理二进制数据 – 获取文件名存储文件
问题:文件名重复,会覆盖
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建文件上传工厂类的对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传类的对象
ServletFileUpload upload = new ServletFileUpload(factory);
try {
//解析请求
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem : list) {//有文本数据(账号到爱好)和二进制数据(file)
if (fileItem.isFormField()){//文本数据
String name = fileItem.getFieldName();
System.out.println("文本数据 -- " + name);
}else {//二进制数据
String path = "D:\\text";//文件存储目录
String fileName = fileItem.getName();//获取文件名
path = path + File.separator + fileName;//拼接路径,File.separator:系统拼接符
InputStream in = fileItem.getInputStream();
FileOutputStream out = new FileOutputStream(path);
IOUtils.copy(in,out);
in.close();
out.close();
}
}
} catch (FileUploadException | IOException e) {
throw new RuntimeException(e);
}
}
运行结果:上传两张图
处理二进制数据 – 利用UUID解决文件名重复的问题(利用UUID保证唯一性)
重新取个名字(唯一性:时间、UUID)—图片资源
问题1:改变了原有的文件名
问题2:代码的可移植性不高(指定了路径-D:\test)
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建文件上传工厂类的对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传类的对象
ServletFileUpload upload = new ServletFileUpload(factory);
try {
//解析请求
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem : list) {//有文本数据(账号到爱好)和二进制数据(file)
if (fileItem.isFormField()){//文本数据
String name = fileItem.getFieldName();
System.out.println("文本数据 -- " + name);
}else {//二进制数据
String path = "D:\\text";//文件存储目录
//获取随机的UUID对象(理解:随机UUID对象 = 系统参数+对象内存地址+算法)
UUID uuid = UUID.randomUUID();
String fileName = fileItem.getName();//获取文件名
fileName=uuid+fileName;//拼接文件名
path = path + File.separator + fileName;//拼接路径
InputStream in = fileItem.getInputStream();
FileOutputStream out = new FileOutputStream(path);
IOUtils.copy(in,out);
in.close();
out.close();
}
}
} catch (FileUploadException | IOException e) {
throw new RuntimeException(e);
}
}
运行结果:两个相同的文件名,前面有uuid
处理二进制数据 – 利用发布路径+时间解决文件名重复问题,并且不会改变原文件名
利用时间保证唯一性:System.currentTimeMillis()
修改发布路径,部署到Tomcat里面
原来:E:\2403workspace\Day23_update\out\artifacts\Day23_update_Web_exploded
现在:D:\apache-tomcat-8.0.49\webapps\Day23_update_Web_exploded
配置Tomcat,点击修改
在Tomcat中的webapps里新建一个路径,将发布路径设置成这个
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建文件上传工厂类的对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传类的对象
ServletFileUpload upload = new ServletFileUpload(factory);
try {
//解析请求
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem : list) {//有文本数据(账号到爱好)和二进制数据(file)
if (fileItem.isFormField()){//文本数据
String name = fileItem.getFieldName();
System.out.println("文本数据 -- " + name);
}else {//二进制数据
// 获取项目发布路径 -- D:\apache-tomcat-8.0.49\webapps\Day23_update_Web_exploded\Update
//注意:Update这个文件不存在
String realPath=request.getServletContext().getRealPath("Update");
//文件存储目录 -- D:\apache-tomcat-8.0.49\webapps\Day23_update_Web_exploded\Update毫秒数
//再加上一个毫秒数,确保万无一失
String path=realPath+File.separator+System.currentTimeMillis();
File file = new File(path);
//如果文件夹不存在就创建文件夹
if (!file.exists()){
file.mkdirs();
}
String fileName = fileItem.getName();//获取文件名
path = path + File.separator + fileName;//拼接路径
InputStream in = fileItem.getInputStream();
FileOutputStream out = new FileOutputStream(path);
IOUtils.copy(in,out);
in.close();
out.close();
}
}
} catch (FileUploadException | IOException e) {
throw new RuntimeException(e);
}
}
运行结果:注意看路径
把获取的数据直接存储到学生对象中,并且文件存储目录 – D:\apache-tomcat-8.0.49\webapps\Day23_update_Web_exploded\用户名,最后用用户名分隔
package com.qf.servlet;
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
StudentRegisterData studentRegisterData = parseRequestForStudent(request);
//打印一下
System.out.println(studentRegisterData.getStudent());
System.out.println(studentRegisterData.getIn());
System.out.println(studentRegisterData.getOut());
}
//解析请求,获取数据封装到学生对象里
//注意:返回学生对象、输入流、输出流
public StudentRegisterData parseRequestForStudent(HttpServletRequest request){
StudentRegisterData studentRegisterData = new StudentRegisterData();
//创建文件上传工厂类的对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传类的对象
ServletFileUpload upload = new ServletFileUpload(factory);
Student student = new Student();
try {
//解析请求
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem : list) {
if(fileItem.isFormField()){//文本数据
String name = fileItem.getFieldName();
//拿到value值,还要设置编码格式
String value = fileItem.getString("UTF-8");
if(name.equals("username")){
student.setUsername(value);
}else if(name.equals("password")){
student.setPassword(value);
}else if(name.equals("name")){
student.setName(value);
}else if(name.equals("sex")){
student.setSex(value);
}else if(name.equals("age")){
student.setAge(Integer.parseInt(value));
}else if(name.equals("hobbies")){
String hobbies = student.getHobbies();
if(hobbies == null){//说明是第一次添加爱好
student.setHobbies(value);
}else{//说明之前已经添加其他的爱好
hobbies = hobbies + "," + value;//拼接一下
student.setHobbies(hobbies);
}
}
}else {//二进制数据
// 获取项目发布路径 -- D:\apache-tomcat-8.0.49\webapps\Day23_update_Web_exploded\Update
//注意:Update这个文件不存在
String realPath=request.getServletContext().getRealPath("Update");
//文件存储目录 -- D:\apache-tomcat-8.0.49\webapps\Day23_update_Web_exploded\用户名
//再加上一个用户名,确保万无一失
String path=realPath+File.separator+student.getUsername();
File file = new File(path);
//如果文件夹不存在就创建文件夹
if (!file.exists()){
file.mkdirs();
}
String fileName = fileItem.getName();//获取文件名
path = path + File.separator + fileName;//拼接路径
InputStream in = fileItem.getInputStream();
FileOutputStream out = new FileOutputStream(path);
studentRegisterData.setIn(in);
studentRegisterData.setOut(out);
student.setPhoto(path);
}
}
} catch (FileUploadException | IOException e) {
throw new RuntimeException(e);
}
studentRegisterData.setStudent(student);
return studentRegisterData;
}
}
StudentRegisterData
学生注册资料包
package com.qf.pojo;
import java.io.InputStream;
import java.io.OutputStream;
public class StudentRegisterData {
private Student student;
private InputStream in;
private OutputStream out;
//...省略
运行结果:
改进RegisterServlet
上面那种拿到学生信息的方式(if循环)太复杂了,可以把他们放在map里面
package com.qf.servlet;
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解析请求,将请求中的数据封装起来
StudentRegisterData studentRegisterData = parseRequestForStudent(request);
//解析请求,获取数据封装到学生对象里
//注意:返回学生对象、输入流、输出流
public static StudentRegisterData parseRequestForStudent(HttpServletRequest request){
StudentRegisterData studentRegisterData = new StudentRegisterData();
//创建文件上传工厂类的对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传类的对象
ServletFileUpload upload = new ServletFileUpload(factory);
HashMap<String, String> map = new HashMap<>();
try {
//解析请求
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem : list) {
if(fileItem.isFormField()){//文本数据
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");
String v = map.get(name);
if(v == null){//说明是第一次添加
map.put(name,value);
}else{//不是第一次添加就需要拼接(多选框的情况)
map.put(name,v + "," + value);
}
}else{//二进制数据
//获取项目发布路径 -- D:\\apache-tomcat-8.0.49\\webapps\\Day23_upload_war_exploded\\upload
String realPath = request.getServletContext().getRealPath("upload");
//文件存储目录 -- D:\\apache-tomcat-8.0.49\\webapps\\Day23_upload_war_exploded\\upload\\用户名
String path = realPath + File.separator + map.get("username");
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
String fileName = fileItem.getName();//获取文件名
//D:\\apache-tomcat-8.0.49\\webapps\\Day23_upload_war_exploded\\upload\\用户名\\tx01.jpg
path = path + File.separator + fileName;//拼接路径
InputStream in = fileItem.getInputStream();
FileOutputStream out = new FileOutputStream(path);
studentRegisterData.setIn(in);
studentRegisterData.setOut(out);
map.put("photo",path);
}
}
} catch (FileUploadException e) {
throw new RuntimeException(e);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry);
}
Student student = new Student();
try {
//将map中的数据映射到实体类对象中
BeanUtils.populate(student,map);//导的包
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
studentRegisterData.setStudent(student);
return studentRegisterData;
}
}
运行结果:
4.4 开始业务
注意:上面一系列操作都是获取请求中的数据,接下来按照学生管理系统中的注册功能往下走就可以了
完整版:RegisterServlet
package com.qf.servlet;
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解析请求,将请求中的数据封装起来
StudentRegisterData studentRegisterData = parseRequestForStudent(request);
Student srdStudent = studentRegisterData.getStudent();
InputStream srdIn = studentRegisterData.getIn();
OutputStream srdOut = studentRegisterData.getOut();
//通过username查询数据库中的学生对象
Student student = null;
try {
student = DBUtils.commonQueryObj(Student.class, "select * from student where username=?", srdStudent.getUsername());
} catch (SQLException e) {
throw new RuntimeException(e);
}
if(student == null){//允许注册
//将数据插入到学生表中
try {
DBUtils.commonUpdate("insert into student(username,password,name,sex,age,hobbies,photo) values(?,?,?,?,?,?,?)",srdStudent.getUsername(),srdStudent.getPassword(),srdStudent.getName(),srdStudent.getSex(),srdStudent.getAge(), srdStudent.getHobbies(),srdStudent.getPhoto());
} catch (SQLException e) {
throw new RuntimeException(e);
}
//将头像存储到本地磁盘
IOUtils.copy(srdIn,srdOut);
srdIn.close();
srdOut.close();
//利用重定向跳转到登录页面
response.sendRedirect("login.jsp");
}else{//不允许注册
srdIn.close();
srdOut.close();
//利用重定向跳转到注册页面
response.sendRedirect("register.jsp");
}
}
//解析请求,获取数据封装到学生对象里
//注意:返回学生对象、输入流、输出流
public static StudentRegisterData parseRequestForStudent(HttpServletRequest request){
StudentRegisterData studentRegisterData = new StudentRegisterData();
//创建文件上传工厂类的对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建文件上传类的对象
ServletFileUpload upload = new ServletFileUpload(factory);
HashMap<String, String> map = new HashMap<>();
try {
//解析请求
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem : list) {
if(fileItem.isFormField()){//文本数据
String name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");
String v = map.get(name);
if(v == null){//说明是第一次添加
map.put(name,value);
}else{//不是第一次添加就需要拼接(多选框的情况)
map.put(name,v + "," + value);
}
}else{//二进制数据
//获取项目发布路径 -- D:\\apache-tomcat-8.0.49\\webapps\\Day23_upload_war_exploded\\upload
String realPath = request.getServletContext().getRealPath("upload");
//文件存储目录 -- D:\\apache-tomcat-8.0.49\\webapps\\Day23_upload_war_exploded\\upload\\用户名
String path = realPath + File.separator + map.get("username");
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
String fileName = fileItem.getName();//获取文件名
//D:\\apache-tomcat-8.0.49\\webapps\\Day23_upload_war_exploded\\upload\\用户名\\tx01.jpg
path = path + File.separator + fileName;//拼接路径
InputStream in = fileItem.getInputStream();
FileOutputStream out = new FileOutputStream(path);
studentRegisterData.setIn(in);
studentRegisterData.setOut(out);
//存储相对路径
map.put("photo","upload" + File.separator + map.get("username") + File.separator + fileName);
}
}
} catch (FileUploadException e) {
throw new RuntimeException(e);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry);
}
Student student = new Student();
try {
//将map中的数据映射到实体类对象中
BeanUtils.populate(student,map);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
studentRegisterData.setStudent(student);
return studentRegisterData;
}
}
LoginServlet
package com.qf.servlet;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求中的数据
String username = request.getParameter("username");
String password = request.getParameter("password");
String userCode = request.getParameter("userCode");
String rememberMe = request.getParameter("rememberMe");
String role = request.getParameter("role");
String sysCode = (String) request.getSession().getAttribute("sysCode");
if (sysCode.equalsIgnoreCase(userCode)){ //验证码是否输入正确
User user=null;
try {
if ("student".equals(role)){
user=DBUtils.commonQueryObj(Student.class,"select * from student where username=? and password=?",username,password);
} else if ("teacher".equals(role)) {
user=DBUtils.commonQueryObj(Student.class,"select * from teacher where username=? and password=?", username, password);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (user!=null){//登录成功
//判断是否记住我
if(rememberMe != null){
//将凭证添加到Cookie中
//cookie保存在浏览器中
response.addCookie(CookieUtils.createCookie("username",user.getUsername(),60*60*24*5));
response.addCookie(CookieUtils.createCookie("name",user.getName(),60*60*24*5));
response.addCookie(CookieUtils.createCookie("role",role,60*60*24*5));
response.addCookie(CookieUtils.createCookie("photo",user.getPhoto(),60*60*24*5));
}
//将数据存储到Session中
//浏览器向服务器发送一个请求,服务器会生成一个session对象,保存在服务器中
HttpSession session = request.getSession();
session.setAttribute("username",user.getUsername());
session.setAttribute("name",user.getName());
session.setAttribute("role",role);
session.setAttribute("photo",user.getPhoto());
response.sendRedirect("index.jsp");
}else{//登录失败 -- 账号或密码错误
request.setAttribute("msg","登录失败--账号或密码错误");
request.getRequestDispatcher("login.jsp").forward(request,response);
}
}else{//登录失败 - 验证码错误
//将数据发送到请求对象(请求域)中,时间在一瞬间,交互很短
//只是在web容器内部流转,仅仅是请求处理阶段
//我们使用request.setAttribute()方法设置了一个名为 “msg” 的属性,并将其值设置为 “登录失败--验证码错误”。
// 然后,我们可以通过请求转发(forward)将这个属性传递给其他组件,如另一个Servlet或JSP页面
request.setAttribute("msg","登录失败--验证码错误");
request.getRequestDispatcher("login.jsp").forward(request,response);
}
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<button οnclick="safeExit()">安全退出</button>
<h1>详情页面</h1>
<h1>欢迎${name}${(role eq "student")?"学员":""}${(role eq "teacher")?"学员":""}进入到学生管理系统</h1>
<img src="${photo}" width="100px" height="100px"><br>
</body>
</html>
最终项目结构:
运行结果:
5.案例-文件下载
主要实现方式有两种
1.超链接下载
2.Servlet下载(有些超链接搞不定的事情就交给Servlet来搞定)
采用流的方式来读和写
设置响应的头部信息(告诉客户端是以附件的形式下载)
response.setHeader(“Content-disposition”, “attachment;fileName=”+fileName);
项目结构:导包,在web里建download文件夹放图片和压缩包
注意:浏览器能够识别的文件会展示,不能够识别的文件就下载(它会直接识别展示算法.jpg这张图片,而BMI资源.zip就直接在浏览器中下载)
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--
注意:浏览器能够识别的文件会展示,不能够识别的文件就下载
-->
<%--<a href="download/算法.jpg">下载图片</a>--%>
<a href="DownloadServlet">下载图片</a>
<a href="download/BMI资源.zip">下载压缩文件</a>
</body>
</html>
DownloadServlet
package com.qf.servlet;
@WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取需要下载文件的路径
String realPath = request.getServletContext().getRealPath("download\\算法.jpg");
//截取出文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
//设置编码格式
fileName= URLEncoder.encode(fileName,"UTF-8");
//设置响应头信息 -- 告诉浏览器该文件是以附件的形式下载
response.setHeader("Content-disposition", "attachment;fileName="+fileName);
//通过IO流向浏览器传输文件数据
FileInputStream in = new FileInputStream(realPath);
ServletOutputStream out = response.getOutputStream();
byte[] bs = new byte[1024];
int len;
while ((len=in.read(bs))!=-1){
out.write(bs,0,len);
}
}
}
总结
1.文件上传 – 学生注册上传头像,并且展示
2.文件下载
注意:利用Servlet向客户端说明以附件的形式下载数据