一.文件的上传
(一)基本概念及其入门案例 1.什么是文件上传:将本地的文件上传到服务器端。 2.应用:百度网盘,上传照片,上传附件。 3.javaweb端实现文件上传; 客户端:需要文件的输入项 <input type="file"/> 必须有三点设置: 1)type="file" name 必须有 name="myfile" 2)form表单 method="post"提交方式 (get参数显示在url上,get数据大小1k) 3)form表单 enctype="multipart/form-data" 编码格式 服务端:写一段文件上传的程序。 requestl.getInputStream(); 获取输入流 System.out.write(); 4.fileupload 文件上传的组件 1)jspsmartupload 上传组件,嵌入在jsp中。model1时代,jsp。 2)jsp+servlet时代 fileuplaod5.fileupload的jar commons-fileupload-1.2.1jar包和commons-io-1.4jar包 要一起使用。 依赖。
package cn.itcast.servlet;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.List;import java.util.UUID;import javax.servlet.ServletException;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.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;import cn.itcast.util.UploadUtil;public class UploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String filedesc = request.getParameter("filedesc"); System.out.println("文件描述:"+filedesc); // 获取输入流 //InputStream in = request.getInputStream(); // 打印控制台上 /*int b; while((b = in.read()) != -1){ System.out.write(b); } System.out.flush();*/ if(!ServletFileUpload.isMultipartContent(request)){ throw new RuntimeException("请设置正确的enctype"); } /** * 1.创建磁盘文件项工厂 */ DiskFileItemFactory factory = new DiskFileItemFactory(); // 设置内存缓冲区的大小 factory.setSizeThreshold(2*1024*1024); //2M // 设置临时文件的存储位置 String temppath = this.getServletContext().getRealPath("/temp"); File filetemp = new File(temppath); factory.setRepository(filetemp); /** * 2.创建文件上传类 */ ServletFileUpload upload = new ServletFileUpload(factory); // 设置上传文件的总大小 upload.setSizeMax(50L*1024*1024); // 50M // 设置文件名称的编码 upload.setHeaderEncoding("UTF-8"); /** * 3.解析request */ try { Listlist = upload.parseRequest(request); /** * 4.循环遍历list集合,拿到fileItem对象,判断是否普表单项 */ for (FileItem fileItem : list) { // isFormField() if(fileItem.isFormField()){ // 普通表单项 // 获取参数的名称 String name = fileItem.getFieldName(); // 获取值 //String value = fileItem.getString(); String value = fileItem.getString("UTF-8"); System.out.println(name+" = "+value); }else{ // 文件上传项 // 获取文件的名称 String filename = fileItem.getName(); // 先判断filename不能空 if(filename == null || filename.trim().length() == 0){ throw new RuntimeException("请选择文件"); } // 解决IE6的问题 D:\class\resource\hello.txt int index = filename.lastIndexOf("\\"); if(index != -1){ filename = filename.substring(index+1); } //解决文件名重名的问题 filename = UUID.randomUUID().toString()+"_"+filename; // 目录分离 String dir = UploadUtil.getRanromDir(filename); System.out.println("文件名称:"+filename); // 获取输入流 InputStream in = new BufferedInputStream(fileItem.getInputStream()); // 先获取upload的绝对路径 String filepath = this.getServletContext().getRealPath("/upload"+dir); // 创建多级目录 new File(filepath).mkdirs(); // 创建file对象 File file = new File(filepath,filename); // 输出流 OutputStream os = new BufferedOutputStream(new FileOutputStream(file)); int b; while((b = in.read()) != -1){ os.write(b); } os.close(); in.close(); // 删除临时文件(必须写在流关闭之后) fileItem.delete(); } } } catch (FileUploadException e) { e.printStackTrace(); } } public static void main(String[] args) { System.out.println(System.getProperty("java.io.tmpdir")); }}
(二)入门案例存在的问题 1.IE6上传文件的问题: 产生原因:把文件的绝对路径传过来了。 解决办法:切割。把文件名称切出来。 // 解决IE6的问题 D:\class\resource\hello.txt int index = filename.lastIndexOf("\\"); if(index != -1){ filename = filename.substring(index+1); } 2.注意事项(*****) String filedesc = request.getParameter("filedesc"); 在文件上传 enctype="multipart/form-data"拿不到值了。 想拿到值就下面方法。 // 获取参数的名称 String name = fileItem.getFieldName(); // 获取值 String value = fileItem.getString();(三)文件上传的核心类及其API 1.磁盘文件项工厂类 DiskFileItemFactory 1)DiskFileItemFactory(int sizeThreshold, java.io.File repository) 第一个参数内存缓冲区的大小 第二个参数临时文件的存储位置 内存缓冲区:上传文件时,文件首先会上传到内存缓冲区中,上传的文件的大小超过设置的内存缓冲区的大小,就会产生临时文件。 临时存储位置:用来保存临时文件的。 2)void setSizeThreshold(int sizeThreshold) 设置内存缓冲区的大小 默认10k 3)void setRepository(java.io.File repository) 设置临时文件存储位置 System.getProperty("java.io.tmpdir") C:\Users\ADMINI~1\AppData\Local\Temp\ 2. 文件上传类 ServletFileUpload 1)static boolean isMultipartContent(javax.servlet.http.HttpServletRequest request) 判断enctype是否是multipart方式 2)java.util.List parseRequest(javax.servlet.http.HttpServletRequest request) 解析request 返回list<FileItem>集合 3)void setSizeMax(long sizeMax) 设置上传所有文件的总大小 和 void setFileSizeMax(long fileSizeMax) 设置单个上传文件的大小 4)(*****)void setHeaderEncoding(java.lang.String encoding) 设置编码 可以解决中文文件名乱码的问题 5)void setProgressListener(ProgressListener pListener) 设置进度条的监听器 进度条速度 剩余时间 剩余大小
3. 文件项FileItem
1)boolean isFormField() 判断是否是普通表单项还是文件上传项 if(fileItem.isFormFiele()){ // 表单 2)java.lang.String getFieldName() 获取参数的名称 3)java.lang.String getString() 获取值 4)(*****)java.lang.String getString(java.lang.String encoding) 设置表单中文的编码 解决普通表单项的中文乱码的问题 }else{ // 文件 5)java.io.InputStream getInputStream() 获取输入流 6)java.lang.String getName() 获取文件名称 } 7)void delete() 删除临时文件((必须写在流关闭之后))(四)多文件上传案例(js控制) 需求:多文件上传。(五)上传文件的扩展
1.上传文件存放目录问题: 1)在webroot目录下,安全级别较低,允许用户直接访问。 购物商城的网站:京东。2)上传文件目录访问WEB-INF目录下,安全级别较高。通过程序。
例子:视频网站。 2.文件名重名的问题 解决办法:UUID+"_"+文件名称 3.解决一个目录内文件过多的问题(目录分离算法) 1)根据上传文件的时间(周,月) 2)根据上传文件的数量(3000) 3)根据用户创建一个文件夹(张三,李四) 4)根据唯一文件名的hashcode值算法。二.文件的下载(一)基本概念及其入门案例 1.什么的文件的下载:将服务器的文件下载到本地。 2.应用:百度网盘,下载歌曲,下载图片。 3.javaweb实现文件的下载: 1)超链接下载 <a href="文件的绝对路径">文件名称</a> 浏览器可以解析你文件的格式。浏览器直接打开。 2)程序的文件下载。 接收文件的名称,获取download的绝对路径,并且拼接file对象,读入到输入流中。 两点注意:两个头一个流 两个响应头:设置Content-Type 属性 MIME类型 设置Content-Disposition 值attachment;filename= + 文件名称 以附件的形式打开。 一个响应流:向浏览器输出 response.getOutputStream()(二)文件下载扩展案例
需求:在磁盘随便指定一个目录,要把该目录下的所有文件及其子目录下的所有文件列在页面上,并且提供下载。 采用广度非递归的遍历,依赖于数据结构。队列 FIFO 先进先出 JDK5.0 提供了接口 Queuepackage cn.itcast.servlet;import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * 下载的入门案例 * @author Administrator * */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"); // 获取download的绝对路径 String filepath = this.getServletContext().getRealPath("/download"); // 创建file对象 File file = new File(filepath,filename); // 读入到输入流 InputStream in = new BufferedInputStream(new FileInputStream(file)); // 设置两个头 String mimeType = this.getServletContext().getMimeType(filename); // 设置类型 response.setContentType(mimeType); // 设置以附件形式打开 response.setHeader("Content-Disposition", "attachment;filename="+filename); // 输出流 OutputStream os = response.getOutputStream(); int b; while((b = in.read()) != -1){ os.write(b); } os.close(); in.close(); }}
2.get方式提交 中文乱码 filepath = new String(filepath.getBytes("ISO-8859-1"),"UTF-8");
3.IE6中文乱码
产生原因:代码没有问题。IE6对中文的编码有bug。 解决办法:自己编码。URLEncoder.encode(f.getCanonicalPath(), "UTF-8") 4.弹出的下载框显示的中文乱码三.JavaMail(邮件)(一)邮件的基本概念及其传输过程 1.为什么学习邮件:比较好的用户体验,比较火的技术。 2.常见邮件:祝福邮件,通知邮件,垃圾邮件 3.基本概念 1)邮件服务器:是一台电脑,装关于邮件服务器的软件。收发邮件。 2)电子邮箱:邮件服务器上的账号,在邮件服务器分配一块空间,用来保存邮件。 3)邮件的传输协议: 发送邮件协议:SMTP协议 默认端口 25 接收邮件协议:POP3协议 默认端口 110 接收邮件协议:IMAP协议 默认端口 143 区别:允许不用下载,直接在服务器端可以修改。 gmail 支持IMAP 4.邮件的传输过程 看图七(二)通过telnet命令手动发送邮件(网络) 1.如果是win7的系统,需要手动开启telnet命令。如果xp不用。 2.发送邮件的协议(SMTP) 1)telnet smtp.sina.com 25 链接新浪的发送邮件的服务器 2)ehlo hi 打个招呼 3)auth login 是否需要登陆认证 4)输入用户名 (必须要经过BASE64进行编码) 5)输入密码 6)mail from:<javamail_day@sina.com> 发件人 7)rcpt to:<javamail_day@163.com> 收件人 8)Data RFC822文档(规范) 9)输入邮件内容(RFC822文档) 10). 代表邮件的结束 11)quit 断开链接 3.RFC822文档 包含邮件头 和邮件体,中间用空行分隔。 邮件头: from:<javamail_day@sina.com> 发件人 to:<javamail_day@163.com> 收件人 subject:girl 邮件的标题 邮件体: I LOVE YOU TOO TOO 4.接收邮件的协议 POP3协议 telnet pop3.163.com 110 链接接收邮件服务器 user 输入用户名 pass 输入密码 stat 返回邮件的数量 list 返回邮件列表结合 retr 2 访问第二封邮件 quit 端口链接(三)邮件服务器,客户端安装及其telnet命令发送邮件(本机)
1.安装邮件服务器 配置:工具--服务器设置--修改域名(estore.com) 新建账号:账号--新建账号。 2.安装客户端软件 安装foxmail。 配置:建立新的账户:bbb@estore.com 密码111 指定邮件服务器:localhost(四)通过JavaMail创建简单的邮件 1.javamial sun官方提供api,关于邮件的api。 2.下载jar包 javamail1_4_4和jaf-1_1_1 包,必须一起使用,依赖。 JDK6.0之后 jaf内置。如果是JDK1.6版本之前,需要引入jaf的包。 3.入门案例。 1)Session 链接服务器会话。 2)Message 邮件对象 3)Transport 发送邮件工具类 4.邮件的内容打印在控制台上保存 java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream 产生的原因:myeclipse自带的jar与javamail的jar包冲突导致。 解决办法: