JavaEE

JavaWeb基础恢复之发邮件、上传、下载

2018-04-22  本文已影响25人  平安喜乐698
目录
    1. 发邮件
    2. 上传
    3. 下载
1. 发邮件
  1. 概念
邮件服务器
    类似于邮局(作为中间者,将发件人写好的邮件传递给收件人)。如:sina、sohu、163
电子邮箱
    用户在邮件服务器上申请的一个账户。

邮件传输协议
    发送邮件,需要遵循一定的通讯规则
        SMTP协议
            用来定义这种通讯规则。
            处理用户smtp请求(邮件发送请求)的服务器称之为SMTP服务器(邮件发送服务器)。
    接收邮件,也需要遵循一定的通讯规则
        POP3协议
            用来定义这种通讯规则

发件/收件步骤
    发件人点击发送邮件按钮
        1.通过smtp协议连接并发送邮件到发件邮箱所属的smtp服务器1上;
        2.smtp服务器1通过smtp协议将邮件发送到收件邮箱所属的smtp服务器2上,并存储在收件箱账号所拥有的存储空间中。
    收件人
        1.通过pop3协议连接POP3服务器;
        2.POP3服务器从收件箱账号所拥有的存储空间中查阅邮件显示给收件人。

SMTP协议(说明)
    1.和连接上的smtp服务器打声招呼
        ehlo hello
    2.登陆smtp服务器(用户名密码必须Base64加密)
        auth login
    3.发件邮箱,收件邮箱
      MAIL FROM:发件邮箱
      RCPT TO:收件邮箱
    4.邮件内容
        DATA
        From: 发件邮箱
        To:收件邮箱
        Subject: 主题
        空格
        邮件内容
    5.表示邮件内容完毕
        . 
    6. 断开连接
        QUIT 

POP3协议(说明)
        user username --登录邮箱的用户名(不需Base64加密)
        pass password --登录邮箱使用的密码(不需Base64加密)
        retr 1  --读取第一封邮件(内容经过Base64加密)
        stat
            返回邮箱里面的邮件数量以及邮件占用的空间大小信息
  list 数字
            返回某一封邮件的统计信息
        quit 
            断开与POP3服务器的连接
用来获取Base64加密后的用户名密码
        /*System.out.print("请输入用户名:");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String userName = in.readLine();
        System.out.print("请输入密码:");
        String password = in.readLine();
        BASE64Encoder encoder = new BASE64Encoder();
        System.out.println("编码后的用户名为:" + encoder.encode(userName.getBytes()));
        System.out.println("编码后的密码为:" + encoder.encode(password.getBytes()));*/
        
用来获取Base64解密后的邮件内容
        BASE64Decoder decoder = new BASE64Decoder();
        //邮件主题的Base64编码
        String emailSubject = "=?GBK?B?08q8/rLiytQ=?=";
        //邮件文本内容的Base64编码
        String emailPlainContent = "vPK1pbXE08q8/reiy82y4srUo6E=";
        //带html标签和邮件内容的Base64编码
        String emailHtmlContent = "PFA+vPK1pbXE08q8/reiy82y4srUo6E8L1A+";
        //将使用Base64编码过后的文本内容再使用Base64来解码
        emailSubject = new String(decoder.decodeBuffer(emailSubject),"GBK");
        emailPlainContent = new String(decoder.decodeBuffer(emailPlainContent),"GBK");
        emailHtmlContent = new String(decoder.decodeBuffer(emailHtmlContent),"GBK");
        System.out.println("邮件标题:"+emailSubject);
        System.out.println("邮件内容:"+emailPlainContent);
        System.out.println("带html标签的邮件内容:"+emailHtmlContent);

RFC882文档

    规定了如何编写一封简单的邮件(纯文本邮件),包含邮件头和邮件体两部分(使用空行分隔)。

邮件头包含:
    from字段     --指明发件人
    to字段       --指明收件人
    subject字段   --指明邮件主题
    cc字段       --抄送,将邮件发送给收件人的同时抄送给另一个收件人,收件人可以看到邮件抄送给了谁
    bcc字段      --密送,将邮件发送给收件人的同时将邮件秘密发送给另一个收件人,收件人无法看到邮件密送给了谁
邮件内容
    具体内容

RFC882文档 不能发送图片、附件

MIME协议

    是对RFC822文档的升级和补充
    MIME协议描述的邮件称之为MIME邮件
    MIME协议描述的数据称之为MIME消息
对于一封复杂邮件,如果包含了多个不同的数据,MIME协议规定了要使用分隔线对多段数据进行分隔,并使用Content-Type头字段对数据的类型、以及多个数据之间的关系进行描述
JavaMail创建邮件
    基于MIME协议,可用于创建复杂邮件。

API
    Message类:创建邮件
    Transport类:发送邮件
    Store类:接收邮件
    Session类:会话,连接客户端与邮件服务器并建立绘话

步骤:
    1. 创建session
    2.创建message
    3.创建transport连接服务器,发送邮件,关闭连接。
  1. 简单使用
  1. jar包
下载所需jar包(mail.jar、activation.jar)
    放在WEB-INF的lib下

Oracle官网下载mail.jar包
Oracle官网下载activation.jar包

  1. 相关文件

注册页

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'MyJsp.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
    <form action="${pageContext.request.contextPath}/servlet/RegisterServlet" method="post">
        用户名:<input type="text" name="username"><br/>
        密码:<input type="password" name="password"><br/>
        邮箱:<input type="text" name="email"><br/>
        <input type="submit" value="注册">
    </form>
  </body>
</html>

注册成功后的显示页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'message.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
    ${message}
  </body>
</html>

处理表单请求

package com.sst.cx;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       

    public RegisterServlet() {
        super();
        // TODO Auto-generated constructor stub
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try{
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String email = request.getParameter("email");
            User user = new User();
            user.setEmail(email);
            user.setPassword(password);
            user.setUsername(username);
            
            System.out.println("把用户信息注册到数据库中");
            //用户注册成功之后就使用用户注册时的邮箱给用户发送一封Email
            //发送邮件是一件非常耗时的事情,因此这里开辟了另一个线程来专门发送邮件
            SendMail send = new SendMail(user);
            //启动线程,线程启动之后就会执行run方法来发送邮件
            send.start();
            
            //注册用户
            //new UserService().registerUser(user);
            request.setAttribute("message", "恭喜您,注册成功,我们已经发了一封带了注册信息的电子邮件,请查收,如果没有收到,可能是网络原因,过一会儿就收到了!!");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
        }catch (Exception e) {
            e.printStackTrace();
            request.setAttribute("message", "注册失败!!");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }
}

用户类

package com.sst.cx;

public class User {

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    private String username;
    private String password;
    private String email;
}

发送邮件类

package com.sst.cx;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SendMail extends Thread {

    // 发件邮箱
    private String from = "chenxiang698@sohu.com";
    // 发件邮箱的用户名
    private String username = "chenxiang698";
    // 发件邮箱的密码
    private String password = "密码";
    // 发送邮件的服务器
    private String host = "smtp.sohu.com";
    
    // 用户模型
    private User user;
    public SendMail(User user){
        this.user = user;
    }
    
    /* 重写run方法的实现,在run方法中发送邮件给指定的用户
     * @see java.lang.Thread#run()
     */
    @Override
    public void run() {
        try{
            // 1.创建Session
            // 参数
            Properties prop = new Properties();
            // 设置 服务器
            prop.setProperty("mail.host", host);
            // 设置 协议
            prop.setProperty("mail.transport.protocol", "smtp");
            // 设置 是否认证
            prop.setProperty("mail.smtp.auth", "true");
            // 设置 端口
            prop.setProperty("mail.smtp.port", "25");
            // 设置 超时时间
            prop.setProperty("mail.smtp.timeout","1000");
            // 设置 开启tls
            prop.put("mail.smtp.starttls.enable", "true");
            // 
            Session session = Session.getInstance(prop);
            session.setDebug(true);
            // 2.创建邮件
            Message message = createEmail(session,user);
            // 3.连接邮箱服务器并登录邮箱 ,发送邮件,关闭连接
            Transport ts = session.getTransport();
            ts.connect(host, username, password);
            ts.sendMessage(message, message.getAllRecipients());
            ts.close();
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    /**
    * @Method: createEmail
    * @Description: 创建要发送的邮件
    * 
    *
    * @param session
    * @param user
    * @return
    * @throws Exception
    */ 
    public Message createEmail(Session session,User user) throws Exception{
        // 创建邮件
        MimeMessage message = new MimeMessage(session);
        // 设置 发件邮箱
        message.setFrom(new InternetAddress(from));
        // 设置 收件邮箱
        message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getEmail()));
        // 设置 邮件主题
        message.setSubject("用户注册邮件");
        
        // 设置 邮件内容
        String info = "恭喜您注册成功,您的用户名:" + user.getUsername() + ",您的密码:" + user.getPassword() + ",请妥善保管,如有问题请联系网站客服!!";
        message.setContent(info, "text/html;charset=UTF-8");
        // 保存
        message.saveChanges();

/*
带图片

        // 文本
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("这是一封邮件正文带图片<img src=''>的邮件", "text/html;charset=UTF-8");
        // 图片
        MimeBodyPart image = new MimeBodyPart();
        DataHandler dh = new DataHandler(new FileDataSource("图片路径"));
        image.setDataHandler(dh);
        image.setContentID("xxx.jpg");
        // 描述数据关系
        MimeMultipart mm = new MimeMultipart();
        mm.addBodyPart(text);
        mm.addBodyPart(image);
        mm.setSubType("related");

        message.setContent(mm);
        message.saveChanges();
        // 保存邮件到本地
        message.writeTo(new FileOutputStream("保存路径"));
*/

/*
带附件

       MimeBodyPart text = new MimeBodyPart();
        text.setContent("使用JavaMail创建的带附件的邮件", "text/html;charset=UTF-8");
        
        // 创建邮件附件
        MimeBodyPart attach = new MimeBodyPart();
        DataHandler dh = new DataHandler(new FileDataSource("src\\2.jpg"));
        attach.setDataHandler(dh);
        attach.setFileName(dh.getName());  //
        
        // 创建容器描述数据关系
        MimeMultipart mp = new MimeMultipart();
        mp.addBodyPart(text);
        mp.addBodyPart(attach);
        mp.setSubType("mixed");
        
        message.setContent(mp);
        message.saveChanges();
*/

/*
图片+附件

        //正文
        MimeBodyPart text = new MimeBodyPart();
        text.setContent("xxx这是女的xxxx<br/><img src='cid:aaa.jpg'>","text/html;charset=UTF-8");
        
        //图片
        MimeBodyPart image = new MimeBodyPart();
        image.setDataHandler(new DataHandler(new FileDataSource("src\\3.jpg")));
        image.setContentID("aaa.jpg");
        
        //附件1
        MimeBodyPart attach = new MimeBodyPart();
        DataHandler dh = new DataHandler(new FileDataSource("src\\4.zip"));
        attach.setDataHandler(dh);
        attach.setFileName(dh.getName());
        
        //附件2
        MimeBodyPart attach2 = new MimeBodyPart();
        DataHandler dh2 = new DataHandler(new FileDataSource("src\\波子.zip"));
        attach2.setDataHandler(dh2);
        attach2.setFileName(MimeUtility.encodeText(dh2.getName()));
        
        //描述关系:正文和图片
        MimeMultipart mp1 = new MimeMultipart();
        mp1.addBodyPart(text);
        mp1.addBodyPart(image);
        mp1.setSubType("related");
        
        //描述关系:正文和附件
        MimeMultipart mp2 = new MimeMultipart();
        mp2.addBodyPart(attach);
        mp2.addBodyPart(attach2);
        
        //代表正文的bodypart
        MimeBodyPart content = new MimeBodyPart();
        content.setContent(mp1);
        mp2.addBodyPart(content);
        mp2.setSubType("mixed");
        
        message.setContent(mp2);
        message.saveChanges();
*/
        return message;
    }
}
  1. 如果连接失败
    检查账号密码
    打开发件邮箱,开启POP3/SMTP服务、IMAP/SMTP服务
2. 上传
浏览器上传是将文件以流的形式提交到服务器


上传需注意:
    1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
    2、为防止文件覆盖,要为上传文件产生一个唯一的文件名。
    3、为防止一个目录下出现太多文件,要使用hash算法打散存储。
    4、要限制上传文件的最大值。
    5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。

存储文件位于
/Users/用户名/Workspaces/MyEclipse 2015/.metadata/.me_tcat7/webapps/项目名/下
1. 下载common-fileupload.jar、common-io.jar

Apache官网下载common-fileupload.jar
Apache官网下载common-io.jar

相关文件

上传文件jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'Upload.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
   <form action="${pageContext.request.contextPath}/servlet/UploadServlet" enctype="multipart/form-data" method="post">
        上传用户:<input type="text" name="username"><br/>
        上传文件1:<input type="file" name="file1"><br/>
        上传文件2:<input type="file" name="file2"><br/>
        <input type="submit" value="提交">
    </form>
  </body>
</html>

上传文件处理类

package com.sst.cx;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;




/**
 * Servlet implementation class UploadServlet
 */
@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public UploadServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
                //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
                String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
                //上传时生成的临时文件保存目录
                String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
                File tmpFile = new File(tempPath);
                if (!tmpFile.exists()) {
                    //创建临时目录
                    tmpFile.mkdir();
                }
                
                //消息提示
                String message = "";
                try{
                    //使用Apache文件上传组件处理文件上传步骤:
                    //1、创建一个DiskFileItemFactory工厂
                    DiskFileItemFactory factory = new DiskFileItemFactory();
                    //设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
                    factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
                    //设置上传时生成的临时文件的保存目录
                    factory.setRepository(tmpFile);
                    //2、创建一个文件上传解析器
                    ServletFileUpload upload = new ServletFileUpload(factory);
                    //监听文件上传进度
                    upload.setProgressListener(new ProgressListener(){
                        public void update(long pBytesRead, long pContentLength, int arg2) {
                            System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
                            /**
                             * 文件大小为:14608,当前已处理:4096
                                文件大小为:14608,当前已处理:7367
                                文件大小为:14608,当前已处理:11419
                                文件大小为:14608,当前已处理:14608
                             */
                        }
                    });
                     //解决上传文件名的中文乱码
                    upload.setHeaderEncoding("UTF-8"); 
                    //3、判断提交上来的数据是否是上传表单的数据
                    if(!ServletFileUpload.isMultipartContent(request)){
                        //按照传统方式获取数据
                        return;
                    }
                    
                    //设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
                    upload.setFileSizeMax(1024*1024);
                    //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
                    upload.setSizeMax(1024*1024*10);
                    //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
                    List<FileItem> list = upload.parseRequest(request);
                    for(FileItem item : list){
                        //如果fileitem中封装的是普通输入项的数据
                        if(item.isFormField()){
                            String name = item.getFieldName();
                            //解决普通输入项的数据的中文乱码问题
                            String value = item.getString("UTF-8");
                            //value = new String(value.getBytes("iso8859-1"),"UTF-8");
                            System.out.println(name + "=" + value);
                        }else{//如果fileitem中封装的是上传文件
                            //得到上传的文件名称,
                            String filename = item.getName();
                            System.out.println(filename);
                            if(filename==null || filename.trim().equals("")){
                                continue;
                            }
                            //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
                            //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
                            filename = filename.substring(filename.lastIndexOf("\\")+1);
                            //得到上传文件的扩展名
                            String fileExtName = filename.substring(filename.lastIndexOf(".")+1);
                            //如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法
                            System.out.println("上传的文件的扩展名是:"+fileExtName);
                            //获取item中的上传文件的输入流
                            InputStream in = item.getInputStream();
                            //得到文件保存的名称
                            String saveFilename = makeFileName(filename);
                            //得到文件的保存目录
                            String realSavePath = makePath(saveFilename, savePath);
                            //创建一个文件输出流
                            FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);
                            //创建一个缓冲区
                            byte buffer[] = new byte[1024];
                            //判断输入流中的数据是否已经读完的标识
                            int len = 0;
                            //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
                            while((len=in.read(buffer))>0){
                                //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
                                out.write(buffer, 0, len);
                            }
                            //关闭输入流
                            in.close();
                            //关闭输出流
                            out.close();
                            //删除处理文件上传时生成的临时文件
                            //item.delete();
                            message = "文件上传成功!";
                        }
                    }
                }catch (FileUploadBase.FileSizeLimitExceededException e) {
                    e.printStackTrace();
                    request.setAttribute("message", "单个文件超出最大值!!!");
                    request.getRequestDispatcher("/message.jsp").forward(request, response);
                    return;
                }catch (FileUploadBase.SizeLimitExceededException e) {
                    e.printStackTrace();
                    request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!");
                    request.getRequestDispatcher("/message.jsp").forward(request, response);
                    return;
                }catch (Exception e) {
                    message= "文件上传失败!";
                    e.printStackTrace();
                }
                request.setAttribute("message",message);
                request.getRequestDispatcher("/message.jsp").forward(request, response);
    }
    
    /**
    * @Method: makeFileName
    * @Description: 生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称
    * 
    * @param filename 文件的原始名称
    * @return uuid+"_"+文件的原始名称
    */ 
    private String makeFileName(String filename){  //2.jpg
        //为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
        return UUID.randomUUID().toString() + "_" + filename;
    }
    
    /**
     * 为防止一个目录下面出现太多文件,要使用hash算法打散存储
    * @Method: makePath
    * @Description: 
    *
    *
    * @param filename 文件名,要根据文件名生成存储目录
    * @param savePath 文件存储路径
    * @return 新的存储目录
    */ 
    private String makePath(String filename,String savePath){
        //得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
        int hashcode = filename.hashCode();
        int dir1 = hashcode&0xf;  //0--15
        int dir2 = (hashcode&0xf0)>>4;  //0-15
        //构造新的保存目录
        String dir = savePath + "\\" + dir1 + "\\" + dir2;  //upload\2\3  upload\3\5
        //File既可以代表文件也可以代表目录
        File file = new File(dir);
        //如果目录不存在
        if(!file.exists()){
            //创建目录
            file.mkdirs();
        }
        return dir;
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

}
3. 下载

获取要下载的文件列表处理类

package com.sst.cx;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class FileListServlet
 */
@WebServlet("/FileListServlet")
public class FileListServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

     public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 获取上传文件的目录
            String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload");
            // 存储要下载的文件名
            Map<String,String> fileNameMap = new HashMap<String,String>();
            // 递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到map集合中
            listfile(new File(uploadFilePath),fileNameMap);//File既可以代表一个文件也可以代表一个目录
            // 将Map集合发送到listfile.jsp页面进行显示
            request.setAttribute("fileNameMap", fileNameMap);
            request.getRequestDispatcher("/fileList.jsp").forward(request, response);
        }
        
        /**
        * @Method: listfile
        * @Description: 递归遍历指定目录下的所有文件
        * 
        * @param file 即代表一个文件,也代表一个文件目录
        * @param map 存储文件名的Map集合
        */ 
        public void listfile(File file,Map<String,String> map){
            //如果file代表的不是一个文件,而是一个目录
            if(!file.isFile()){
                //列出该目录下的所有文件和目录
                File files[] = file.listFiles();
                //遍历files[]数组
                for(File f : files){
                    //递归
                    listfile(f,map);
                }
            }else{
                /**
                 * 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
                    file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi
                    那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分
                 */
                String realName = file.getName().substring(file.getName().indexOf("_")+1);
                //file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复
                map.put(file.getName(), realName);
            }
        }
        

    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

}

文件下载处理类

package com.sst.cx;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class DownloadServlet
 */
@WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 得到要下载的文件名
        String fileName = request.getParameter("filename");  //23239283-92489-阿凡达.avi
        fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
        // 上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
        String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");
        //通过文件名找出文件的所在目录
        // String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
        String path=fileSaveRootPath;
        //得到要下载的文件
        File file = new File(path + "/" + fileName);
        //如果文件不存在
        if(!file.exists()){
            request.setAttribute("message", "您要下载的资源已被删除!!");
            request.getRequestDispatcher("/message.jsp").forward(request, response);
            return;
        }
        //处理文件名
        String realname = fileName.substring(fileName.indexOf("_")+1);
        //设置响应头,控制浏览器下载该文件
        response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
        //读取要下载的文件,保存到文件输入流
        FileInputStream in = new FileInputStream(path + "/" + fileName);
        //创建输出流
        OutputStream out = response.getOutputStream();
        //创建缓冲区
        byte buffer[] = new byte[1024];
        int len = 0;
        //循环将输入流中的内容读取到缓冲区当中
        while((len=in.read(buffer))>0){
            //输出缓冲区的内容到浏览器,实现文件下载
            out.write(buffer, 0, len);
        }
        //关闭文件输入流
        in.close();
        //关闭输出流
        out.close();
    }
    
    /**
    * @Method: findFileSavePathByFileName
    * @Description: 通过文件名和存储上传文件根目录找出要下载的文件的所在路径
    *
    * @param filename 要下载的文件名
    * @param saveRootPath 上传文件保存的根目录,也就是/WEB-INF/upload目录
    * @return 要下载的文件的存储目录
    */ 
    public String findFileSavePathByFileName(String filename,String saveRootPath){
        int hashcode = filename.hashCode();
        int dir1 = hashcode&0xf;  //0--15
        int dir2 = (hashcode&0xf0)>>4;  //0-15
        String dir = saveRootPath + "\\" + dir1 + "\\" + dir2;  //upload\2\3  upload\3\5
        File file = new File(dir);
        if(!file.exists()){
            //创建目录
            file.mkdirs();
        }
        return dir;
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request,response);
    }

}

文件下载列表页jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'fileList.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>
  
  <body>
      <c:forEach var="me" items="${fileNameMap}">
        <c:url value="/servlet/DownloadServlet" var="downurl">
            <c:param name="filename" value="${me.key}"></c:param>
        </c:url>
        ${me.value}<a href="${downurl}">下载</a>
        <br/>
        </c:forEach>
  </body>
</html>
上一篇下一篇

猜你喜欢

热点阅读