学习Java的日子 Day63 文件上传,文件下载,上传头像案例

news2024/9/20 18:26:10

文件上传下载

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向客户端说明以附件的形式下载数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1974609.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VMware安装Centos虚拟机使用NAT模式无法上网问题处理

NAT模式无法上网问题处理 Centos7与Ubuntu使用同一个NAT网络&#xff0c;Ubuntu正常访问互联网&#xff0c;Centos无法正常访问。 处理方案&#xff1a; cd /etc/sysconfig/network-scripts vi ifcfg-ens33 修改配置项&#xff1a; 重启网络&#xff1a; service network resta…

vue的nextTick是下一次事件循环吗

如题&#xff0c;nextTick的回调是在下一次事件循环被执行的吗&#xff1f; 是不是下一次事件循环取决于nextTick的实现&#xff0c;如果是用的微任务&#xff0c;那么就是本次事件循环&#xff1b;否则如果用的是宏任务&#xff0c;那么就是下一次事件循环。 我们看下Vue3中…

STM32L051K8U6-开发资料

STM32L051测试 &#xff08;四、Flash和EEPROM的读写&#xff09;-云社区-华为云 (huaweicloud.com) STM32L051测试 &#xff08;四、Flash和EEPROM的读写&#xff09; - 掘金 (juejin.cn) STM32L0 系列 EEPROM 读写&#xff0c;程序卡死&#xff1f;_stm32l0片内eeprom_stm3…

Android studio配置代码模版

一、背景&#xff1a; 在工作中&#xff0c;总是要写一些重复的代码&#xff0c;特别是项目有相关规范时&#xff0c;就会产生很多模版代码&#xff0c;每次要么复制一份&#xff0c;要么重新写一份新的&#xff0c;很麻烦&#xff0c;于是我就在想&#xff0c;能不能像创建一…

tomato靶场

扫描网址端口 访问一下8888 我们用kali扫描一下目录 访问这个目录 产看iofo.php源码&#xff0c;发现里面有文件包含漏洞 访问/etc/passwd/发现确实有文件包含漏洞 远程连接2211端口 利用报错&#xff0c;向日志文件注入木马&#xff0c;利用文件包含漏洞访问日志文件 http:/…

现代前端架构介绍(第二部分):如何将功能架构分为三层

远离JavaScript疲劳和框架大战&#xff0c;了解真正重要的东西 在这个系列的前一部分 《App是如何由不同的构建块构成的》中&#xff0c;我们揭示了现代Web应用是由不同的构建块组成的&#xff0c;每个构建块都承担着特定的角色&#xff0c;如核心、功能等。在这篇文章中&#…

手机市场回暖,为何OPPO却“遇冷”?

在智能手机这片红海中&#xff0c;OPPO曾以其独特的营销策略和创新的产品设计&#xff0c;一度占据国内市场的领先地位。然而&#xff0c;近期的数据却揭示了OPPO正面临前所未有的挑战&#xff0c;销量下滑、库存高企&#xff0c;昔日的辉煌似乎已成过眼云烟。 当整个手机市场逐…

单个或两个及以上java安装与环境变量配置

目录 java下载地址&#xff1a; 1.安装java 1.1 安装程序 1.2选择安装路径 1.3等待安装 2.首先&#xff0c;进入环境变量 2.1 找到设置&#xff08;第一个win11&#xff0c;第二个win10&#xff09; 2.2 进入到系统高级系统设置&#xff08;第一个win11&#xff0c;第二…

快捷生成vue模板插件

Vetur < 就可以选择快捷键

Java多线程实现的两种方式

Java多线程实现的两种方式 1. 继承Thread类2. 实现Runnable接口3.总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1. 继承Thread类 直接继承java.lang.Thread类&#xff0c;并重写其run方法。这种方式简单直接&#xff0c;但限制了类…

Python3接口测试框架的整体布局与设计

实战项目整体布局概览 本实战项目基本的层级结构如下&#xff1a; 习惯性的命名规则&#xff0c;把所有的辅助类py文件放在commonsrc这个包里面&#xff0c;如数据库配置封装文件、接口配置封装文件等&#xff1b;辅助类py文件在整个项目中初期代码写好后一般是不会去大范围修…

Character.AI的联合创始人Noam Shazeer将加入谷歌;又一个开源平替llamacoder;和mem0一样的动态记忆框架

✨ 1: Character.AI 创始人回归google Character.AI的联合创始人Noam Shazeer将加入谷歌 Character.AI的联合创始人Noam Shazeer和Daniel De Freitas离开公司&#xff0c;重新加入Google旗下的DeepMind研究团队。Google签署了一项非独占性协议&#xff0c;使用Character.AI的…

Java8新特性(二) Stream与Optional详解

Java8新特性&#xff08;二&#xff09; Stream与Optional详解 一. Stream流 1. Stream概述 1.1 基本概念 Stream&#xff08;java.util.stream&#xff09; 是Java 8中新增的一种抽象流式接口&#xff0c;主要用于配合Lambda表达式提高批量数据的计算和处理效率。Stream不是…

远程控制电脑的正确姿势,3大神器助你秒变技术达人!

现在的生活节奏快得跟打鼓似的&#xff0c;不管是在家工作、帮朋友修电脑&#xff0c;还是想控制家里的播放器放个电影&#xff0c;远程控制电脑这事儿越来越重要了。有没有遇到过想用电脑却够不着的尴尬&#xff1f;别急&#xff0c;今天咱们就来看看怎么搞定远程控制电脑&…

快瞳宠物AI识别赋能养宠智能设备,让品牌大有可为

随着国内养宠市场的不断完善与成熟&#xff0c;许多家庭养宠理念从“健康养宠”向“育儿式养宠”的升级&#xff0c;国内宠物行业向高质量发展阶段迈进&#xff0c;宠物经济增长迅猛。报告显示&#xff0c;2024年宠物智能设备货架电商年销售额达2.5亿&#xff0c;增速近30%。内…

记录一次学习过程(msf、cs的使用、横向渗透等等)

目录 用python搭建一个简单的web服务器 代码解释 MSF msfvenom 功能 用途 查看payloads列表 msfconsole 功能 用途 msfvenom和msfconsole配合使用 来个例子 msf会话中用到的一些命令 在windows中net user用法 列出所有用户账户 显示单个用户账户信息 创建用户账…

x-cmd mod | x jq - 轻量级的 JSON 处理工具

目录 简介使用语法参数子命令x jq openx jq repl 简介 jq 是一个轻量级的 JSON 处理工具&#xff0c;是由 Stephen Dolan 于 2012 年开发。 使用语法 x jq [SUB_COMMAND] <#n>参数 参数描述#n继承 jq 子命令或参数选项 子命令 名称描述x jq open用浏览器打开 jqplay…

Axure入门及快速上手的法宝元件库:解锁高效原型设计之旅

在当今快速迭代的数字产品时代&#xff0c;原型设计成为了连接产品创意与实现之间不可或缺的桥梁。Axure RP&#xff0c;作为一款强大的交互原型设计工具&#xff0c;凭借其易用性、灵活性和丰富的功能&#xff0c;成为了设计师和产品经理的首选。它不仅能够帮助用户快速创建高…

Vue3 + cropper 实现裁剪头像的功能(裁剪效果可实时预览、预览图可下载、预览图可上传到SpringBoot后端、附完整的示例代码和源代码)

文章目录 0. 前言1. 裁剪效果&#xff08;可实时预览&#xff09;2. 安装 cropper3. 引入 Vue Cropper3.1 局部引入&#xff08;推荐使用&#xff09;3.2 全局引入 4. 在代码中使用4.1 template部分4.2 script部分 5. 注意事项6. SpringBoot 后端接收图片6.1 UserController.ja…

无线蓝牙耳机哪个品牌好?甄选四款专业蓝牙耳机品牌推荐

随着市场上品牌和型号众多&#xff0c;挑选出最适合自己的蓝牙耳机却变成了一项不小的挑战&#xff0c;不同的用户有着不同的需求——有的人追求音质、有的人注重续航、有的人在意舒适度&#xff0c;还有的人看重的是设计与功能性&#xff0c;那么无线蓝牙耳机哪个品牌好&#…