Upload&Download&VCode&Longin/out

Upload&Download&VCode&Longin/out

Login & Logout


Login

  • login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




Insert title here



    

用户登录

${errorMsg}

验证码 验证码
  • LoginServlet.java
@WebServlet("/login")
public class LoginServlet extends HttpServlet {

  private IUserDAO dao;
  
  @Override
  public void init() throws ServletException {
    dao = new UserDAOImpl();
  }
  
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    // 设置请求参数编码只对post方法有用,一般的表单都是post一般的url请求都是get
    req.setCharacterEncoding("utf-8");
    // 定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件
    resp.setContentType("text/html;charset=utf-8");
    // 验证用户名密码
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    // 调用业务方法处理请求
    User user = dao.checkLogin(username, password);
    if (user == null) {
      // 返回重新登录的页面
      // 将错误信息放到请求作用域中
      req.setAttribute("errorMsg", "用户名密码错误");
      req.getRequestDispatcher("/login.jsp").forward(req, resp);
      //------验证码的验证
      // 获取用户填写的验证码
      String userRandomCode = req.getParameter("userRandomCode");
      // 获取生成的二维码
      Object randomCode = req.getSession().getAttribute("RANDOMCODE_IN_SESSSION");
      // 对比用户输入的验证码和生成的验证码是否匹配
      if (!StringUtil.hasLength(userRandomCode) || !userRandomCode.equals(randomCode)) {
        // 返回登录界面
        req.setAttribute("errorMsg", "验证码不能为空或者验证码错误或者验证码无效");
        resp.getRequestDispatcher("/login.jsp").forward(req, resp);
        return;
      }
      //-----
      // 跳转到登录后的页面
      // 登录成功以后将用户信息放入到session中
      req.getSession().setAttribute("USER_IN_SESSION", user);
      resp.sendRedirect(req.getContextPath() + "/product");
    }
  }
}

Logout

  • LogoutServlet.java
 protected void service(HttpServletRequest req, HttpServletResponse resp) throws Exception {
   // 销毁session对象
   req.getSession().invalidate();
   resp.sendRedirect(req.getContextPath() + "/login.jsp");
 }

文件上传


  • 准备工作
    • 创建一个包含上传控件的表单
      • 表单的提交方式必须是post,因为get方式的只允许1kb的数据
      • 文件上传的enctype必须是multipart/form-data,不对表中的数据编码,按照二进制形式传输,此时表单的数据就不能通过request.getParameter(String name)来获取
      • 表单上必须有一个上传控件
  • 上传表单示例
姓名: 头像:
  • 如何实现文件上传
    • 导包commons-fileupload.jarcommons-io.jar
  • 注意

表单中的控件对应着API中的FileItem

  • 示例代码
// 验证表单是否满足文件上传的条件(提交的方式为post,enctype是否以multipart/开头)
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
if (!isMultipart) {
  // 不满足条件就什么都不做
  return;
}
// 创建一个FileItem的工厂类
FileItemFactory factory = new DiskFileItemFactory();
// 创建一个文件上传的处理器(装饰模式)
ServletFileUpload upload = new ServletFileUpload(factory);
// 解析请求,将页面中的表单控件解析成FileItem
// FileItem:对应着表单中的一个控件
List items = upload.parseRequest(req); 
// 解析请求,将页面中的表单控件解析成FileItem
List items = upload.parseRequest(req);
for (FileItem fileItem : items) {
  // 获取控件的名称
  System.out.println(fileItem.getFileName());
  // 判断控件是普通控件还是上传控件
  if (fileItem.isFormField()) {
    // 普通控件
    // 获取控件的值
    System.out.println(fileItem.getString());
    // 解决乱码
    System.out.println(fileItem.getString("UTF-8"));
  } else {
    // 上传控件
    // 文件的MIME类型
    System.out.println(fileItem.getContentType());
    // 文件的大小
    System.out.println(fileItem.getSize());
    // 文件的名称
    System.out.println(fileItem.getName());
    File f = new File("C://", fileItem.getName());
    try {
      // 将文件写到服务端的磁盘
      fileItem.write(f);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
}

文件上传的细节处理

  • 文件名处理

使用UUID来生成随机数作为文件的文件名

// 生成文件名
String fileName = UUID.randomUUID().toString();
// 获取文件的后缀名
String extension = FilenameUtils.getExtension(fileItem.getName());
File f = new File("C:/", fileName + "," + extension);
  • 注意

在实际开发中,将上传的文件保存到项目的一个目录下

// 使用相对路径
String realPath = req.getServletContext().getRealPath("/upload/files");

缓存大小和临时目录

  • 缓存大小

文件上传的功能通常需要约束文件的大小,目的是防止用户随意上传文件。

// 约束一个上传文件的大小
upload.setFileSizeMax(fileSizeMax);

// 约束一次完整请求中上传文件的总大小
upload.setSizeMax(siezeMax);
  • 临时目录

将比较大的文件存储到一个临时目录中,小文件任然可以读取到内存中

// 创建一个FileItem工厂类
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置上传文件缓冲大小,超过缓存大小就会被保存到临时目录中
factory.setSizeThreshold(50 * 1024);
// 设置临时目录的位置,默认在服务器中的/temp
factory.setRepository(new File("c:/temp"));

文件下载


  • 设置响应报头contentType: application/x-msdownload

如果不设置响应报头,有的浏览器IE6,可能会直接将需要下载的内容按照二进制的文件输出出来

  • Content-Disposition:attachment

由用户选择将相应的实体内容保存到一个文件中

response.setHeader("Content-Disposistion", "attachment;filename=建议保存名称")

  • 下载文件乱码问题
// IE
response.setHeader("Content-Disposition","attachment;filename=" + new String(filename.getByes("UTF-8"),"ISO8859-1"));
// 非IE
response.setHeader("Content-Disposition","attachement;filename="+URLEncoder.encode(filename,"utf-8"));
  • 示例代码
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    String filename = req.getParameter("filename");
    String download = req.getServletContext().getRealPath("/WEB-INF/download");
    String path = download + "\\" + filename;
    // 设置输出的MIME类型
    resp.setContentType("application/x-msdownload");
    // 获取字节输出流
    ServletOutputStream out = resp.getOutputStream();
    // 在非IE中设置文件名的方式
    String userAgent = req.getHeader("User-Agent");
    if (userAgent.contains("MSIE")) {
      // IE
      filename = URLEncoder.encode(filename, "UTF-8");
    } else {
      // 非IE
      filename = new String(filename.getBytes("UTF-8"), "ISO-8859-1");
    }
    // 设置响应头信息
    resp.setHeader("Content-Disposition", "attachment; filename=" + filename);
    Files.copy(Paths.get(path), out);
  }
}

你可能感兴趣的:(Upload&Download&VCode&Longin/out)