zoukankan      html  css  js  c++  java
  • JavaWeb之文件上传与下载&邮件技术(十八)

    文件上传

    简介

    最近发现这几篇很少写简介,说自己没时间写,可能是说服自己吧。总之能多写就多写。还有个一直存在的问题,每天写的博客质量不是很好。再次说服自己,现在处于学习阶段,写博客为了巩固知识点,以便后期作复习使用。其实我每次写博客之前笔记老早都在nopad++上写好了,所以大部分在wlw上直接粘贴的,请见谅

    1. 文件上传必要前提

    1. form表单:属性enctype必须取值为multipart/form-data
    	enctype的默认值是:application/x-www-form-urlencoded
    	form的enctype属性和请求消息头“Content-Type”作用是一样的,告知服务器请求正文的类型
    2. 提交请求方式:post
    3. 提供<input type="file" name="f1"/>的上传输入域

    2. form请求正文内容

    1. application/x-www-form-urlencoded:
    	请求正文:name=abc&password=123&gender=female
    
    2. 当form的enctype="multipart/form-data"时的正文内容:
    	-----------------------------7de771e40c46         分界符分成了三部分:每一部分都是用MIME协议进行描述的
    	Content-Disposition: form-data; name="name"
    
    	goudan
    	-----------------------------7de771e40c46
    	Content-Disposition: form-data; name="f1"; filename="a.txt"
    	Content-Type: text/plain
    
    	aaaaaaaaaaa
    	-----------------------------7de771e40c46
    	Content-Disposition: form-data; name="f2"; filename="b.txt"
    	Content-Type: text/plain
    
    	bbbbbbbbbbbbbbbbbbb
    	-----------------------------7de771e40c46--
    

    3. 文件上传的原理

    对请求正文是multipart/form-data类型的数据进行解析

    4. 借助第三方的组件实现文件上传

    commons-fileupload
    常用的类:
    	DiskFileItemFactory:产生FileItem的工厂类
    	new DiskFileItemFactory(int sizeThreshold, File repository)
    	sizeThreshold:指定一个缓存大小。默认大小10Kb
    	repository:磁盘临时文件的存放目录。默认是当前用户的系统临时文件目录
    	new DiskFileItemFactory()
    
    	ServletFileUpload:核心解析器
    	FileItem:代表着一个表单上传输入域

    文件上传结合案例进行拓展知识

    1. 文件上传和9个注意问题及解决方案

    文件上传
    	1. 解决乱码问题,request设置编码(可以解决上传文件名的乱码问题)
    	2. 获取保存文件的资源路径
    	3. 判断该路径是否存在,若不存在,就创建
    	4. 判断表单提交的enctype是否multipart/form-data
    	5. 得到文件上传的对象
    	6. 转换用户的请求得到一个List<FileItem>
    	7. 遍历该集合,获取每一个对象
    	8. 判断每个对象是否是普通字段,如果是普通字段,获取字段名和字段值(可以指定编码)
    	9. 如果不是普通字段,获取该对象的MIME类型
    	10. 判断该类型是否是image类型(限制只能下载image类型)
    	11. 获取上传文件的文件名
    	12. 根据hashcode生成两级子目录的绝对路径
    		获取文件的hashcode,根据位运算和左移拼接子目录,判断文件夹是否存在,返回拼接之后的目录
    	13. 获取输出流关联到生成的目录
    	14. 通过遍历的对象获取输入流
    	15. IOUtils工具拷贝
    	16. 关闭流之后,勿忘删除临时文件
    
    文件上传要考虑的9个问题
    1、如何保证服务器的安全
    	把保存文件的目录放在WEB-INF下
    2、中文编码问题:
    	a、普通字段中文值
    		FileItem.getString("UTF-8");
    	b、中文的文件名
    		request.setCharacterEncoding("UTF-8");
    3、防止一个文件夹下的文件太多的问题
    	分目录存储
    	a、分日期创建:今天上传的文件放在以今天日期命名的文件夹中
    	
    	b、用文件名的hashCode计算存放目录		
    4、防止同一个文件夹的文件重名
    ID  STORE_PATH 					OLD_FILENAME NEW_FILENAME USER_ID
    1   /WEB-INF/files/20140109		a.txt		  UUID1.txt		1 
    2   /WEB-INF/files/20140109		a.txt		  UUID2.txt		2 
    
    不用数据库
    UUID1_a.txt
    UUID2_a.txt
    5、限制上传文件的大小:
    a、单个文件大小
    ServletFileUpload.setFileSizeMax(2*1024*1024);
    b、总文件大小
    ServletFileUpload.setSizeMax
    6、临时文件的问题:commons-fileupload,上传使用缓存,默认是10kb,超出10kb的上传文件,使用磁盘作为临时缓存(临时文件,存在哪里?默认是系统的临时目录)
    更改临时文件存放目录:DiskFileItemFactory.setRepository(File file)
    FileItem.delete():删除临时文件。在关闭流之后调用。
    
    7、限制上传文件的类型:
    只允许上传图片:
    判断上传文件的扩展名
    +
    判断上传内容的MIME类型
    8、多文件上传时,用户没传全
    						if(item.getName().equals("")){
    							continue;
    						}
    9、文件上传进度条:异步与服务器进行通信,间隔性的通信
    计算上传文件的进度比例
    给ServletFileUpload注册一个监听器。

    2. 文件下载及显示上传的文件列表

    一. 显示下载页面ListServlet
    1. 获取服务器中的保存资源路径
    2. 建立map集合用于存储UUID文件名和原始文件名
    3. 遍历资源路径所有文件
    	3.1 判断文件是否是文件,如果是文件,获取文件名称
    		根据分隔符分隔获取原始文件名
    		将UUID文件名和原始文件名添加到map集合中
    	3.2 否则不是文件的话,继续递归文件夹
    
    4. 将map设置到request域中
    5. 转发到显示下载列表listfiles.jsp
    
    二、下载列表页面设计
    	1. listfiles.jsp-->遍历requestScope域中的map
    	2. 因为链接资源有文件名,将每个资源路径加上<c:url>标签,注意这里使用的真实路径,所以是key的值
    	3. 显示下载内容,连接到<c:url>标签的连接
    	
    三、 DownloadServlet类
    	1. 设置编码问题,告诉浏览器输出编码格式
    	2. 获取要下载的文件名,进行编码再解码
    	3. 获取该文件的的真实路径,通过再创建hashcode结构目录
    	4. 创建输入流关联该文件
    	5. 得到一个输出流
    	6. 拷贝输入流到输出流中
    	7. 关闭流,提示文件下载成功

     

    JavaMail邮件开发

    1. 邮件开发协议

    1. SMTP协议:(重点)
        发送邮件的协议    Simple Message Transfer Protocal
        使用的端口:25
    2. POP协议:
        接收邮件的协议    Post Office Protocal
        使用的端口:110

    2. 邮件收发过程理解

    其实你可以把邮件服务器理解为邮局!如果你需要给朋友寄一封信,那么你需要把信放到邮筒中,这样你的信会“自动”到达邮局,邮局会把信邮到另一个省市的邮局中。然后这封信会被送到收信人的邮箱中。最终收信人需要自己经常查看邮箱是否有新的信件。
    其实每个邮件服务器都由SMTP服务器和POP3服务器构成,其中SMTP服务器负责发邮件的请求,而POP3负责收邮件的请求

    3. 手工telnet收发邮件

    手工发送一封邮件(熟悉SMTP协议)准备:
    itheimacloud@163.com iamsorry
    
    itheimacloud     aXRoZWltYWNsb3Vk
    iamsorry    aWFtc29ycnk=
    
    smtp.163.com   发送邮件的服务器   smtp.qq.com    smtp.126.com
    pop.163.com 
    
    开始发送:
    telnet smtp.163.com 25
    ---------------------------------以下属于SMTP协议的内容
    ehlo wyj          向服务器打招呼
    
    auth login             请求认证
    
    aXRoZWltYWNsb3Vk
    
    aWFtc29ycnk=
    
    mail from:<itheimacloud@163.com>
    rcpt to:<itheima14@163.com>
    
    data               标识邮件内容开始(内容需要遵守一定的格式:RFC822规范)
    from:itheimacloud@163.com
    to:itheima14@163.com
    subject:this is test mail
    
    aaaaaaaaaaaaaaa
    bbbbbbbbbbbbbbb
    .                   <CR><LF>.代表结束 
    ----------------------------------
    quit

    4. JavaMail概述及注意事项

    1. JavaMail概述
    Java Mail是由SUN公司提供的专门针对邮件的API,主要Jar包:mail.jar、activation.jar
    2.注意事项 
    在MyEclipse中,会自动给web项目导入javax.mail包中的类,但是不全(其实是只有接口,而没有接口的实现类),所以只靠MyEclipse中的类是不能运行java mail项目的,但是如果这时你再去自行导入mail.jar时,就会出现冲突。
    处理方案:到下面路径中找到javaee.jar文件,把javax.mail删除!!!
    D:Program FilesMyEclipseCommonpluginscom.genuitec.eclipse.j2eedt.core_10.0.0.me201110301321datalibrarysetEE_5

    5. 利用java实现邮件发送过程

    1.设置一些必要的协议,远程邮件服务器地址
    	Properties props = new Properties();
    	props.setProperty("mail.transport.protocol", "smtp");
    	props.setProperty("mail.host", "smtp.163.com");
    2. 根据第一步设置相关邮件发送的信息,得到一个session对象<==>连接
    	Session session = Session.getInstance(props);
    	session.setDebug(true);用户查看底层发送邮件的相关代码
    
    3. 得到一个Message对象,message对象
    	MimeMessage msg = new MimeMessage(session);
    	3.1 发送者
    		msg.setFrom(new InternetAddress("itheimacloud@163.com"));
    	3.2 接受者	发送TO 抄送cc,密送bcc
    		msg.setRecipients(RecipientType.TO, "itheima14@163.com");
    	3.3 主题
    		msg.setSubject("明天去爬山!");
    	3.4 正文
    		msg.setText("<a href='http:localhost:8080/day20_email/servlet/EmailServlet?activeCode="+UUID.randomUUID().toString()+"'>激活邮件地址,要想激活必须先点我</a>");
    
    4. 创建一个邮件发送对象
    	Transport tp = session.getTransport();
    	4.1 邮件发送对象(设置登录远程邮件服务器账户和密码)
    		tp.connect("itheimacloud","iamsorry");
    	4.2 发送
    		tp.sendMessage(msg, msg.getAllRecipients());
    	4.3 邮件发送对象进行关闭
    		tp.close();
  • 相关阅读:
    Python爬虫入门教程 59-100 python爬虫高级技术之验证码篇5-极验证识别技术之二
    CouchDB简介
    零成本打造抖音IP,轻松实现月入过万,90%的人都不懂
    couchdb集群搭建
    汽车测评详细操作流程,一篇赚300+
    基于docker部署的微服务架构: docker环境下的zookeeper和kafka部署
    零成本的互联网赚钱项目,都是怎么做的?
    SQuirrel连接hive配置
    本人有8万启动资金,做点什么生意好呢?
    PHP实现自己活了多少岁
  • 原文地址:https://www.cnblogs.com/codingpark/p/4277999.html
Copyright © 2011-2022 走看看