资讯专栏INFORMATION COLUMN

本周总结(文件上传,下载,邮件)

luxixing / 3384人阅读

摘要:文件上传上传对表单限制表单中需要添加文件表单项用户名照片上传上传对限制文件上传不能使用这个方法在表单为时,它作废了。

文件上传 1.上传对表单限制

method="post"

enctype="multipart/form-data"

表单中需要添加文件表单项:

${msg }

用户名;
照 片:
2.上传对Servlet限制

文件上传不能使用BaseServlet

request.getParametere("xxx");这个方法在表单为enctype="multipart/form-data"时,它作废了。它永远都返回null

ServletInputStream request.getInputStream();包含整个请求的体!

3.上传三步

导入jar(commons-fileupload)

commons-fileupload.jar

commons-io.jar

相关类:

工厂:DiskFileItemFactory

解析器:ServletFileUpload

表单项:FileItem

 1.创建工厂:DiskFileItemFactory factory = new DiskFileItemFactory();
 2.创建解析器:ServletFileUpload sfu = new ServletFileUpload(factory);
 3.使用解析器来解析request,得到FileItem集合:List fileItemList = sfu.parseRequest(request);

4.FileItem

boolean isFormField():是否为普通表单项!返回true为普通表单项,如果为false即文件表单项!

String getFieldName():返回当前表单项的名称;

String getString(String charset):返回表单项的值;

String getName():返回上传的文件名称

long getSize():返回上传文件的字节数

InputStream getInputStream():返回上传文件对应的输入流

void write(File destFile):把上传的文件内容保存到指定的文件中。

String getContentType();获取上传的文件的类型

5.上传的细节

保存到WEB-INF下!(目的是不让浏览器直接访问到)

有的浏览器上传的文件名是绝对路径,这需要切割

目录打散

 哈希打散:  
     通过文件名称得到int值,即调用hashCode()
     它int值转换成16进制0~9, A~F
     获取16进制的前两位用来生成目录,目录为二层!例如:1B2C3D4E5F,/1/B/保存文件。

6.代码
public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        
        /*
         * 上传三步
         */
        // 工厂,设置缓存,超过20k,向目录保存
        DiskFileItemFactory factory = new DiskFileItemFactory(20*1024, new File("F:/f/temp"));
        // 解析器
        ServletFileUpload sfu = new ServletFileUpload(factory);
        //sfu.setFileSizeMax(100 * 1024);//限制单个文件大小为100K
        //sfu.setSizeMax(1024 * 1024);//限制整个表单大小为1M
        
        // 解析,得到List
        try {
            List list = sfu.parseRequest(request);
            FileItem fi = list.get(1);
            
            /*
             * 1. 得到文件保存的路径
             */
            String root = this.getServletContext().getRealPath("/WEB-INF/files/");
            /*
             * 2. 生成二层目录
             *   1). 得到文件名称
             *   2). 得到hashCode
             *   3). 转发成16进制
             *   4). 获取前二个字符用来生成目录
             */
            String filename = fi.getName();//获取上传的文件名称
            /*
             * 处理文件名的绝对路径问题
             */
            int index = filename.lastIndexOf("");
            if(index != -1) {
                filename = filename.substring(index+1);
            }
            /*
             * 给文件名称添加uuid前缀,处理文件同名问题
             */
            String savename = CommonUtils.uuid() + "_" + filename;
            
            /*
             * 1. 得到hashCode
             */
            int hCode = filename.hashCode();
            String hex = Integer.toHexString(hCode);
            
            /*
             * 2. 获取hex的前两个字母,与root连接在一起,生成一个完整的路径
             */
            File dirFile = new File(root, hex.charAt(0) + "/" + hex.charAt(1));
            
            /*
             * 3. 创建目录链
             */
            dirFile.mkdirs();
            
            /*
             * 4. 创建目录文件
             */
            File destFile = new File(dirFile, savename);
            
            /*
             * 5. 保存
             */
            fi.write(destFile);
            
            
        } catch (FileUploadException e) {
            if(e instanceof FileUploadBase.FileSizeLimitExceededException) {
                request.setAttribute("msg", "您上传的文件超出了100KB!");
                request.getRequestDispatcher("/form.jsp").forward(request, response);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
文件下载 1.下载就是向客户端响应字节数据!
 把一个文件变成字节数组,使用response.getOutputStream()来各应给浏览器!!!
2.下载的要求

两个头一个流!

Content-Type:你传递给客户端的文件是什么MIME类型,例如:image/pjpeg

 通过文件名称调用ServletContext的getMimeType()方法,得到MIME类型!

Content-Disposition:它的默认值为inline,表示在浏览器窗口中打开!attachment;filename=xxx

在filename=后面跟随的是显示在下载框中的文件名称!

流:要下载的文件数据!

自己new一个输入流即可!

3.代码
@Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        /*
         * 两个头一个流
         * 1. Content-Type
         * 2. Content-Disposition
         * 3. 流:下载文件的数据
         */
        String filename = "F:/清白之年.mp3";
        
        // 为了使下载框中显示中文文件名称不出乱码!
        String framename = filenameEncoding("清白之年.mp3", req);
        
        String contentType = this.getServletContext()
                .getMimeType(filename);//通过文件名称获取MIME类型
        String contentDisposition = "attachment;filename=" + framename;
        // 一个流
        FileInputStream input = new FileInputStream(filename);
        
        //设置头
        resp.setHeader("Content-Type", contentType);
        resp.setHeader("Content-Disposition", contentDisposition);
        
        // 获取绑定了响应端的流
        ServletOutputStream output = resp.getOutputStream();
        
        IOUtils.copy(input, output);//把输入流中的数据写入到输出流中。
        
        input.close();
    }
    
    // 用来对下载的文件名称进行编码的!(通用方案)
    public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException {
        String agent = request.getHeader("User-Agent"); //获取浏览器
        if (agent.contains("Firefox")) {
            BASE64Encoder base64Encoder = new BASE64Encoder();
            filename = "=?utf-8?B?"
                    + base64Encoder.encode(filename.getBytes("utf-8"))
                    + "?=";
        } else if(agent.contains("MSIE")) {
            filename = URLEncoder.encode(filename, "utf-8");
        } else {
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
JavaMail

注意:一般邮箱需要开通POP3/SMTP/IMAP功能,发过去邮件很可能在垃圾箱里面

1.导入jar

mail.jar
activation.jar

2.主要类

javax.mail.Session
javax.mail.internet.MimeMessage
javax.mail.Transport

3.代码

无附件

@Test
    public void fun1() throws Exception {
        /*
         * 1. 得到session
         */
        Properties props = new Properties();
        props.setProperty("mail.host", "smtp.163.com");
        props.setProperty("mail.smtp.auth", "true");
        
        Authenticator auth = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("itcast_cxf", "itcast");//账号密码
            }
        };
        
        Session session = Session.getInstance(props, auth);
        
        /*
         * 2. 创建MimeMessage
         */
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress("itcast_cxf@163.com"));//设置发件人
        msg.setRecipients(RecipientType.TO, "itcast_cxf@126.com");//设置收件人
        //msg.setRecipients(RecipientType.CC, "itcast_cxf@sohu.com");//设置抄送
        //msg.setRecipients(RecipientType.BCC, "itcast_cxf@sina.com");//设置暗送
        
        msg.setSubject("这是来自ITCAST的测试邮件");
        msg.setContent("这就是一封垃圾邮件!", "text/html;charset=utf-8");
        
        /*
         * 3. 发
         */
        Transport.send(msg);
    }

有附件

@Test
    public void fun2() throws Exception {
        /*
         * 1. 得到session
         */
        Properties props = new Properties();
        props.setProperty("mail.host", "smtp.163.com");
        props.setProperty("mail.smtp.auth", "true");
        
        Authenticator auth = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("itcast_cxf", "itcast");
            }
        };
        
        Session session = Session.getInstance(props, auth);
        
        /*
         * 2. 创建MimeMessage
         */
        MimeMessage msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress("itcast_cxf@163.com"));//设置发件人
        msg.setRecipients(RecipientType.TO, "itcast_cxf@126.com");//设置收件人
        
        msg.setSubject("这是来自ITCAST的测试邮件有附件");
        
        /*
         * 当发送包含附件的邮件时,邮件体就为多部件形式!
         * 1. 创建一个多部件的部件内容!MimeMultipart
         *   MimeMultipart就是一个集合,用来装载多个主体部件!
         * 2. 我们需要创建两个主体部件,一个是文本内容的,另一个是附件的。
         *   主体部件叫MimeBodyPart
         * 3. 把MimeMultipart设置给MimeMessage的内容!
         */
        MimeMultipart list = new MimeMultipart();//创建多部分内容
        
        // 创建MimeBodyPart
        MimeBodyPart part1 = new MimeBodyPart();
        // 设置主体部件的内容
        part1.setContent("这是一封包含附件的垃圾邮件", "text/html;charset=utf-8");
        // 把主体部件添加到集合中
        list.addBodyPart(part1);
        
        
        // 创建MimeBodyPart
        MimeBodyPart part2 = new MimeBodyPart();
        part2.attachFile(new File("F:/f/白冰.jpg"));//设置附件的内容
        part2.setFileName(MimeUtility.encodeText("大美女.jpg"));//设置显示的文件名称,其中encodeText用来处理中文乱码问题
        list.addBodyPart(part2);
        
        msg.setContent(list);//把它设置给邮件作为邮件的内容。
        
        /*
         * 3. 发
         */
        Transport.send(msg);        
    }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/74232.html

相关文章

  • Nextcloud个人云存储绝佳选择:一键自动安装方法和云盘使用体验

    搭建个人云存储一般会想到ownCloud,堪称是自建云存储服务的经典。而Nextcloud是ownCloud原开发团队打造的号称是下一代存储。初一看觉得口气不小,刚推出来就重新定义了Cloud,真正试用过后就由衷地赞同这个Nextcloud:它是个人云存储服务的绝佳选择。 与ownCloud相比,Nextcloud的功能丝毫没有减弱,甚至由于可以安装云存储服务应用,自制性更强,也更符合用户的...

    Shisui 评论0 收藏0
  • 【趣味连载】攻城狮上传视频与普通人上传视频:序

    摘要:还有就是,我拿到的第一手数据,也不是什么结构化数据,而是一个表格,和一个分散在多个文件夹下的视频资源。原来只有约个视频,都是交给普通人上传的。一生成结构化数据讲述的是,数据如何从普通的文档数据,变成最终可被程序化处理的过程。 前言 我想写一个简单的系列文章。主题很简单,就是记录下面对上传视频需求时,攻城狮和普通人(泛指所有非技术人员)的一些区别。当然,从需求分析到最终完整实现,每个步骤...

    jackwang 评论0 收藏0
  • 【趣味连载】攻城狮上传视频与普通人上传视频:序

    摘要:还有就是,我拿到的第一手数据,也不是什么结构化数据,而是一个表格,和一个分散在多个文件夹下的视频资源。原来只有约个视频,都是交给普通人上传的。一生成结构化数据讲述的是,数据如何从普通的文档数据,变成最终可被程序化处理的过程。 前言 我想写一个简单的系列文章。主题很简单,就是记录下面对上传视频需求时,攻城狮和普通人(泛指所有非技术人员)的一些区别。当然,从需求分析到最终完整实现,每个步骤...

    Towers 评论0 收藏0

发表评论

0条评论

luxixing

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<