文件上传
简介
最近发现这几篇很少写简介,说自己没时间写,可能是说服自己吧。总之能多写就多写。还有个一直存在的问题,每天写的博客质量不是很好。再次说服自己,现在处于学习阶段,写博客为了巩固知识点,以便后期作复习使用。其实我每次写博客之前笔记老早都在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 Files\MyEclipse\Common\plugins\com.genuitec.eclipse.j2eedt.core_10.0.0.me201110301321\data\libraryset\EE_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();