本文共 11632 字,大约阅读时间需要 38 分钟。
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■↓↓↓↓↓↓↓↓↓ Java程序文件上传和下载 ↓↓↓↓↓↓↓↓↓↓↓■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ Java程序上传和下载; 为什么要有? 如果是直接把数据输出到浏览器, 那么部分的二进制文件则用户没法下载, 也会使得某些特殊的网站则无法运行下去, 因为有一些网络提供资源下载是商业行为。 是什么? 是SUN公司制定的位于Java语言一套标准。 作用; 增加了对业务的处理的多样性,和可控性。 特点; 页面必须要按照SUN公司的标准进行配置 ◆◆◆◆◆◆注;在下载和上传中要善于使用URLEncoder.encode("xxx","UTF-8"); 这个URLEncoder类的静态方法,用于转换编码集避免乱码 -----------------------------------↓↓↓↓↓↓↓↓↓ 网络传输的文件类型 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- 网络传输文件类型; 在网络传输中的文件类型是分为大类型和小类型的, 主要是为了便于标识某一些文件的子类型, 因为在网络传输文件的过程中, 也可以必须这些文件的受到破坏。 如;图片文件,有GIF,jpg等后缀文件, 而如果这些文件的后缀都是img那么则会出现损坏, 而且这些文件的所显示的功能和效果都是不一样的, 但是这些文件都是属于image类型的即是图片类型。 常用的文件类型; 1.文本文件 text/xxx ---> text,HTML,JSP,CSS...... 2.图片文件 image/xxx ---> jpg,gif...... ◆◆◆◆◆注;可以在Tomcat ---> conf ---> web.xml 中查找到所需要的文件类型 ---------------------------------------↓↓↓↓↓↓↓↓↓ 文件上传条件 ↓↓↓↓↓↓↓↓↓↓↓--------------------------------------------- 文件上传; 上传一般都是使用开源的解析工具进行开发, 因为如果是开发人员进行手动开发的话会使得效率低下, 而且业务的处理也不够细致,如果是使用工具开发, 那么可以使得效率提高而且在处理的方面, 可以使用开发人员不必考虑太多。 工具; commons-fileupload-1.2.2.jar ---> Apache 主包 comons-io-2.1.jar ---> Apache 辅助包 条件; 1.必须要在后台页面提供form表单 ······因为只有form表单都有提供文件上传的功能和属性 2.<input>标签中的type属性必须要是file ······因为form表单中的<input>标签只有file属性才可以让使用将文件进行上传 ◆◆◆注;给这个<input type="file">标签添加一个multiple属性, 则可以让用户在进行文件上传的时候可以一次选择多个文件进行上传 3.必须要是post提交 ······因为Get提交的大小只有1KB而且Get提交不是提交内容(正文),只是提交文件名而已 4.需要把form表单中的···enctyle···属性设置为···multipart/form-data··· ······因为这个属性是设置请求头的contentType的值,而默认是application/www-form 只有设置称为multipart/form-data才是请求正文类型才能接收数据 -------------------------------------↓↓↓↓↓↓↓↓↓ 文件上传开发步骤 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- 文件上传开发步骤; 1.定义页面必须要按照上面↑↑↑↑↑↑↑的标准 2.导入jar包 3.创建硬盘文件项目工厂类, ---> DiskFileItemFactory 定于文件缓存的位置和大小。 4.创建Servlet上传类对象, ---> ServletFileUpload 传入一个硬盘文件项目工厂类对象, 对上传的文件进行缓存等操作。 ◆◆◆注;可以在Servlet上传类的方法中设置缓存的大小和位置也可以 5.通过Servlet上传类对象的方法解析上传的所有文件。 6.使用文件工具类的方法直接将这个文件写出到硬盘中。 ◆◆◆注;一般的文件是不存放在数据库的[资源宝贵]。。。。。。。 --------------------------------------↓↓↓↓↓↓↓↓↓ 文件上传开发过程 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- 文件上传开发过程; 1.创建硬盘文件项目工厂类对象,设置缓存大小和缓存的位置 ---> DiskFileItemFactory factory = new DiskFileItemFactory(缓存(B)1024*1024,new File(缓存位置)); 2.创建Servlet文件上传类对象,传入一个DiskFileItemFactory对象,用于缓存上传文件 ---> ServletFileUpload upload = new ServletFileUpload(factory); 或 ---> upload.setItemFactory(factory); 通过这个方法 3.调用ServletFileUpload类的方法获取到上传的所有文件, 传入一个request对象,因为用户与服务器进行交互都是通过请求类的。 ---> List<FileItem> list = upload.parseRequest(request); 4.遍历这个List集合,而这些文件都按照Apache提供的, · 而ServletFileUpload这个类继承的了一个抽象的顶层类FileUploadBase, · 而FileUploadBase这个抽象类的parseRequest(RequestContext ctx)方法 · 将这个文件封装为一个FileItem这个接口(标准)的对象,添加到集合中返回。 ···从而才可以调用这个接口的方法对文件进行操作 ···但是FileUploadBase这个抽象类没有实现FileItem这个接口,只是在方法中调用进行封装 ---> for(FileItem fileItem : list){ A.调用FileItem这个接口的方法获取到这个文件名 String name = fileItem.getName(); B.调用FileItem这接口的方法获取到这个上传的文件流 InputStream is = fileItem.getInputStream(); C.使用io.jar包下的FileUtils这个工具类的方法直接将这个上传的文件流写出到硬盘中 FileUtils.copyInputStreamToFile(is[流],new File(写出路径和文件名)); } ◆◆◆注意;在使用copyInputStreamToFile这个方法的时候记得写出的时候是要加上文件名的 -----------------------------------↓↓↓↓↓↓↓↓↓ 文件上传开发细节 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- 文件上传开发细节; 1.创建一个DiskFileItemFactory对象,配置缓存,1M ---> DiskFileItemFactory factory = new DiskFileItemFactory(1024*1024,new File("目录")); 2.创建一个SerlvetFileUpload类对象,并且传入一个配置好缓存的DiskFileItemFactory对象 ---> ServletFileUpload upload = new ServletFileUpload(factory); A.设置上传的文件内容编码集 upload.setHeaderEncoding("UTF-8"); B.限制上传的每一个文件的大小,50M upload.setFileSizeMax([B]50*1024*1024); C.限制上传的全部文件总大小,500M upload.setSizeMax(1024*1024*500); 3.调用方法获取到所有上传的文件,传入一个request对象,因为所有交互都是通过请求对象 ---> List<FileItem> list = upload.parseRequest(request); 4.遍历所有请求的上传文件 for(FileItem fileItem : list){ //A.判断是不是普通表单提交 if(fileItem.isFieldForm()){ //获取到这个普通表单提交的name值 String name = fileItem.getFieldName(); //获取到这个普通表单提交的value值 String value = fileItem.getString(); //获取到这个普通表单提交的value值类型名 Object o = fileItem.getType().getSimpleName; } //获取到文件名 String fileName = fileItem.getName(); //获取到文件提交内容的类型 String type = fileItem.contentType(); //B.判断文件类型是不是图片,设置只接收图片 if(!type.matches("image/[a-zA-Z]")){ System.out.println("只能是图片"); } //C.调用UUID生成一个唯一的系列号,避免文件名重复 String uuid = UUID.randomUUID().toString; //D.获取到上传的文件流 InputStream is = fileItem.getInputStream(); //d.调用文件工具类的方法将这个文件写出 FileUtils.copyInputStreamToFile(is,new File(URLEncoder.encode("c:/" + uuid + fileName,"UTF-8"))); //E.删除缓存的文件 fileItem.delete(); } ◆◆◆◆◆◆注意;在生成UUID和获取到传入的文件名的时候, 最好将文件名的所带的···符号···去除, 和文件名长度最好不要···超过20, 避免出现浏览器···解析文件问题。 而且以上都是Apache提供的工具jar包中的,而不是JDK_API的 ------------------------------------------↓↓↓↓↓↓↓↓↓ 文件下载 ↓↓↓↓↓↓↓↓↓↓↓----------------------------------------------- 文件下载; 一般页面提供给用户下载,一般都是有两种方式。 一、直接下载 ---> 如;直接使用<a>标签嵌套<img>标签 二、程序下载 ---> 使用java代码进行控制 -------------------------------------↓↓↓↓↓↓↓↓↓ 文件下载开发过程 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- 文件下载开发过程; 1.获取到源文件的路径 ---> this.getServletContext.getRealPath("/x");获取到一个相对路径文件的一个绝对路径 2.获取到Servlet的输出流 ---> response.getOutputStream(); 3.获取到源文件的输入流 ---> FileInputStream 4.写出到浏览器 5.关闭流 ◆◆◆◆◆◆注;可以在写出浏览器之前给响应头添加content-disposition属性,提升用户的体验 resposne.setHeader("content-disposition","attachment;filename=" + URLEncoder.encode(源文件路径,"UTF-8")); ----------------------------------------↓↓↓↓↓↓↓↓↓ 文件下载开发过程 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- 文件下载开发过程; 1.获取到文件的路径, 通过这个方法获取到一个相对路径文件的绝对路径 String path = this.getServletContext().getRealPath("文件相对路径"); 2.获取到Servlet的输出流,因为提供文件给用户是响应包的数据 ServletOutputStream stream = resposne.getOutputStream(); 3.获取到当前服务器中的文件输入流 FileInputStrema is = new FileInputStream(path); 4.设置这个响应的Content-disposition的属性, 使得浏览器解析出这个是一个下载从而提升用户体验 responser.setHeader("content-disposition","attachment;filename=" + URLEncodier.encode(path)); 5.将这个文件写出到用户的浏览器中,从而使得用户可以下载到自己的硬盘中 ..................................................................... 6.关闭流 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■↓↓↓↓↓↓↓↓↓ JavaMail ↓↓↓↓↓↓↓↓↓↓↓■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ JavaMail; 为什么要有? 当一个网站的用户注册了, 需要进行邮箱的验证的时候, 如果是人工一个一个的发送, 那么效率低下,用户体验差...... 是什么? 是SUN公司规定的标准,是用于通过Java程序进行发送邮件的操作 作用; 通过业务的逻辑,从而发送邮件给用户,提高安全性,实现业务的多样性...... 特点; 发送基本都是依赖SMTP协议(简单邮件发送协议) 接收基本都是依赖pop3协议(邮件接收协议版本3) --------------------------------------↓↓↓↓↓↓↓↓↓ 邮件发送的方式 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- 常见邮件发送的方式; 1.cmd命令 2.java命令 3.邮件应用 --------------------------------------↓↓↓↓↓↓↓↓↓ 邮件运行原理 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- 邮件运行原理; 一般都是由两台服务器组成的 A、SMTP服务器 ---> 发送邮件 B、POP3服务器 ---> 接收邮件 163.用户A给qq.用户B发送了一封邮件, 而这封邮件先发送到163的SMTP服务器, 163的SMTP服务器则对这封邮件后缀进行解析 解析到了是qq.com的地址, 则会按照smtp.qq.com这个地址将邮件发送的pop3服务器。 ------------------------------------↓↓↓↓↓↓↓↓↓ JavaMail开发步骤 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- JavaMail开发步骤; 1.创建一个Properties类,定义发送的属性 2.通过JavaMail的Session核心类的getDefaultInstance(pro,Atthencator);方法连接数据库 ---> Session 是一个抽象类 ---> Atthenticator 也是一个抽象类 3.创建MimeMessage类传入一个连接服务器的Session类对象 4.调用MimeMessage类的方法定义邮件并且发送 ◆◆◆重◆◆◆注意;如果创建的是普通的java项目而不是web项目, 则需要进行导入jar包 ---> mail.jar 而在MyEclipse中的web项目自带mail.jar可能无法使用则删除在导入 ------------------------------------↓↓↓↓↓↓↓↓↓ JavaMail开发过程 ↓↓↓↓↓↓↓↓↓↓↓------------------------------------------- JavaMail开发过程; 1.创建一个Porperties类对象 properties pro = new Properties(); 2.定义连接数据库的属性 A.定义连接的服务器的地址 pro.setProperty("mail.host","smtp.qq.com"); B.定义是否需要进行验证 pro.setProperty("mail.smtp.auth","true"); 3.通过Session类的静态方法创建一个Session对象,从而连接到服务器 Session session = Session.getDefaultInstance(pro,new Authencator(){ protected javax.mail.PasswordAuthentication getPasswordAuthentication() { //调用PsswordAuthentication类在构造方法中传入密码和账号 return new PasswordAuthentication("账号","密码"); }); 说明; Session是JavaMail中的一个核心类, 而这个类是用于连接邮件服务器的, 传入一个Properties对象, 而这个properties对象是定义好连接服务器的属性的 Authentication是一个抽象类, 而这个类是用于封装账号密码的, 对账号和密码进行加密的。 4.创建一个MimeMessage类传入一个Session对象, 这个类是用于定义邮件格式和数据发送给用户的。 MimeMessage mes = new MimeMessage(session); A.定义发件人信箱,必须要和账号一样,传入一个Address的子类 mes.setFrom(new InternetAddress("xx.qq.com")); B.定义收件人信息 mes.setRecipient(RecipientType.XX,new InternetAddress(收件人邮箱)); 说明; RecipientType有三种发送方式; 1.TO ---> 发送 直接发送 2.CC ---> 抄送 类似A-B-C转发 3.BCC ---> 密送 类似A-D私聊,但是D可以看到B和C的邮件内容 C.添加附件(文件、图片......) ---> ◆可选 i.创建一个附件类 MimeBodyPart part = new MimeBodyPart(); 1.添加一个文件 part.attachFile(new File("附件路径")); 2.添加附件内容 part.setContent("xx","text/plain; charset=UTF-8"); ii.创建一个附件类的容器类 MimeMultipart multipart = new MimeMultipart(); 1.调用方法添加一个好的附件类对象 multipart.addBodyPar(part); D.调用MimeMessage的添加邮件内容方法将这个附件类容器对象传入 1.发送邮件附件 mes.setContent(mutilpart); 2.设置发送邮件正文 mes.setContent("xxx","text/plain; charset=utf-8;"); 3.设置邮件正文为一张网络上一张照片,并且设置为超链接,广告形式 mes.setContent("<a href="http://www.baidu.com"> <img src="网络图片地址"> <a>" , "text/html; charset=UTF-8"); E.调用Transport抽象类的方法将邮件信息发送给服务器 Transport.send(mm); ◆◆◆◆◆注;在发送内容的时候要指定内容在网络中传输的类型 而邮件基本都是使用BASE64进行加密的 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■↓↓↓↓↓↓↓↓↓ 其他 ↓↓↓↓↓↓↓↓↓↓↓■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1、泛型 作用; 1.可以减少代码转换,使得方法更加通用 a_ 自定义类<T>转换 ---> 自定义泛型类 b_ 方法转换 ---> 自定义泛型方法 2.提前预知类运行时异常 a_ 因为在给一个类或方法设置了泛型, 则使得在转换成为不是这个泛型, 所规定的则会报编译时错误。 3.可以限定转换的类型范围 a_ <?> 则是通配所有类型,一般都是为了使得工具不出现警告 b_ <? extends Xx> 只能存放本类和本类下的子类 c_ <? super Xx> 只能存放本类和本类的父类 2、枚举 作用;如;实现一个多选一的功能 在定义枚举类的属性的时候可以定义这个属性的值 ---> A("xxx"); ---> 而这个也会作为一个类似对象的存在 而当这个枚举类提供了一个有参的构造器 通过这个参数的对应成员变量的get方法 进行获取,所以可以理解为一个对象。 3、注解 作用;携带数据 而···注释只是一个说明而已 自定义注解; 语法;@interface Xx{}; 属性语法;类型 名() ---> 修饰符只能是public default ---> 如果在定义属性的时候添加了default "xx", 则在使用这个注解的时候不用显示的赋值 ···使用默认值 ---> 如果属性名是value则在调用的时候, 则可以省略不写属性名 ◆◆◆注;类型不可以是集合, 但是可以是数组。 调用属性;@Xx (Ff=Aa); ---> 普通属性 @Xx (Ee={xx,xx}) ---> 数组属性 常用的元注解; 作用;使得这个自定义注解可以更加灵活的应用 ◆◆注;是声明在这个自定义注解上面的 @Target ({ElementType.Xx}) ---> 定义这个注解的位置,如;属性,方法...... 常用; Type 作用在类 Field 作用在成员变量 Method 作用在方法上 Constractor 作用在构造器上 Parameter 作用在参数 Local_Value 作用在本地值 。。。。。。 ◆◆◆注;默认是全部的作用在全部的位置上 @Retention (RetentionPolicy.X) ---> 设置这注解携带数据的范围 三种范围; Source ---> 源码,当前这个注解元素范围 Class ---> 字节码上有效 ---> 包含了Source Runtime ---> 运行时有效 ---> 包含了Source、Class ◆◆◆注;默认是Class 4、反射 是所有Java对象构建的原理, 任何的类都是通过类加载器加载进内存的, 由类加载器读取指定目录的class文件后, 将class文件中的所有信息封装为不同的类, Method类,Constracter类,Field类,Class正在运行时类, 可以通过这些类的方法获取到对应的相关的信息。 代码; Class x = Yy.getClass(); ---> 获取到Yy这个运行时类对象 Method m = x.getDeclarMethod("方法名"); ---> 获取到这个运行时类对象的所有方法(可见/不可见) m.setAccessible(true); ---> 设置可以访问所有的方法,无视修饰符 ◆◆◆注;如果是final修饰的,则无效 Object o = x.newIstance(); ---> 获取到这个类的实例 m.invoke(o,"xx"); ---> 调用某一个方法并且进行赋值(有参) 5、类加载器 作用;是用于加载所有的类对象的 所有的类都是通过类加载器加载进内存的, 而加载器也是一个类来的,ClassLoader类 Java类加载器内部结构 ↑↑↑ C++程序读取 ↑↑↑ BootStrap ---> 根类加载器 ---> %jdk%/lib/tr.jar 核心类包 ↑↑↑ ExtClassLoader ---> 扩展加载器 ---> %jdk%/lib/ext/*.jar ↑↑↑ AppClassLoader ---> 应用加载器 ---> %app%/bin/* 源码下bin文件夹 ↑↑↑ ClassLoader ---> 类加载器 当前类 ◆◆◆注;这个也是一个内部执行的顺序 ---> C - A - E - B - C+ 类加载器相关的API_ClassLoad基本方法 ---> X.getClassload() ---> 获取到一个类的加载器 getParent() ---> 获取到父类加载器, 可以用while获取到整个结构 如果是null则是根类加载器 Java类加载机制 —— 委托机制 发出;类T由C类加载器发出加载请求给A类加载器, A类加载器则向E类加载器发出请求, E类加载器则向B类加载器发出请求。 处理; 找不到;B类加载器获取到这个请求, ↓↓↓ 则在当前的目录下查找是否有这个类对应的class文件, ↓↓↓ 没有则将这个请求发送给E类加载器,E类加载器重复B类加载器的查找动作 ↓↓↓ 没有抛给A类加载器,A类加载器则会在%app%/bin/*目录下查找 ↓↓↓ 没有这个类对应的class文件则, 会报NotFoundClassException类找不到异常 找到;在提交到根类加载器的时候找到了则加载, 找不到则向下委托,向下委托找到了则加载, 找不到则重复,直到A类加载器找到为止, A类加载器找不到则报错。 ◆◆◆注;必须先提交到B类(根类)加载器才会进行查找文件操作 ◆◆◆注;如果一个类1中还有一个类2, 那么类1被那个类加载器加载到这个类2也是被这个类加载器加载到 委托机制的好处; 1.提高效率,节省资源..... 提高效率是因为是逐层查找,加载的, 那么则不会使得当每一个类加载器, 都有一个同名的文件的时候都要进行加载 2.提高对JDK核心类的安全性...... 因为如果创建java.util包创建了Date类, 那么在查找的时候,因为使用哪个呢? 有了委托机制则只会使用核心包的Date的类 ◆◆◆◆◆注;无论有多少个对象, 都是只有一个类加载器, 因为只是对源class文件进行加载的。 而在new对象的时候有无数个对象, 都是通过反射调用这个类的构造器 ◆◆ 类是对数据的一个抽取,而对象是对这个数据的实现,而对象的实现始终还是指向这个一个类(.class文件)
转载地址:http://ihmxi.baihongyu.com/