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"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
    function random() {
        var obj = document.getElementById("code");
        obj.src = "${pageContext.request.contextPath}/randomCode?" + new Date().toString();
    }
</script>
</head>
<body>
    <h2>用户登录</h2>
    <span style="color: red;">${errorMsg}</span>
    <form action="${pageContext.request.contextPath}/login" method="post">
        <!-- placeholder直接在输入框中给用户看到提示 -->
        <input type="text" name="username" placeholder="用户名" /> 
        <input type="password" name="password" placeholder="密码" />
        <input type="submit" value="登录" /><br /> 
        验证码<input type="text"   name="userRandomCode" />
        <!-- src是生成验证码的Servlet对应的路径 -->
        <img id="code" alt="验证码"    src="${pageContext.request.contextPath }/randomCode" onclick="random();" />
    </form>
</body>
</html>
  • 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)来获取
      • 表单上必须有一个上传控件
  • 上传表单示例
<form action="/upload" method="post" enctype="multipart/form-data">
  姓名:<input name="name" />
  <!-- 上传控件 -->
  头像:<input type="file" name="headImg" />
  <input type="submit" value="提交">
</form>
  • 如何实现文件上传
    • 导包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:对应着表单中的一个控件<input name="name" />
List<FileItem> items = upload.parseRequest(req); 
// 解析请求,将页面中的表单控件解析成FileItem
List<FileItem> 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);
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容