件上传 为什么使用文件上传? 例如社交网站需要提供用户照片. 很多企业内部,商品网站维护时需要上传一些文件 邮箱需要上传附件.... 怎样完成文件上传操作? 浏览器 1.请求方式必须是 post 2.需要使用组件<input type="file" name="f"> 3.表单必须设置encType="multipart/form-data" 4.上传文件的input 中,name属性必须要填写,不然不会上传. 服务器端 通过request对象,获取InputStream,可以将浏览器提交的所有请求正文读取到. ------------------------------------------------------------------------------------- 文件上传的插件 commons-fileupload 它是常用的一个文件上传工具 使用时要导入两个jar包 commons-fileupload-1.2.1.jar commons-io-1.4.jar 快速入门 1.设置浏览器端 <form action="${pageContext.request.contextPath}/upload2" method="post" enctype="multipart/form-data"> <input type="file" name="f"> <input type="submit" value="上传"> </form> 2.在服务器端操作 // 1.创建一个 DiskFileItemFactory DiskFileItemFactory factory = new DiskFileItemFactory(); // 2.创建一个ServletFileUpload ServletFileUpload upload = new ServletFileUpload(factory); // 3.完成上传操作 try { // 3.1 得到所有上传项 List<FileItem> items = upload.parseRequest(request); // 3.2遍历上传项 for (FileItem item : items) { // 3.3判断是否是上传组件 if (!item.isFormField()) { // 3.4 将文件真正上传 IOUtils.copy(item.getInputStream(), new FileOutputStream( "d:/upload/a.txt")); } } } catch (FileUploadException e) { e.printStackTrace(); } ============================================================= 文件上传 后台步骤 1. 创建并使用DiskFileItemFactory 进行上传的设置(缓冲区大小,临时文件仓库) 2. 创建ServletFileUpload类,加载DiskFileItemFactory中的配置. 3. 使用ServletFileUpload 解析Request对象. => 获得请求正文中每个分隔符之间的内容 封装的FileItem对象 集合. 4. 遍历FileItem对象集合. //判断 当前FIleItem是否是一个字段类型 //不是字段类型 => 该FileItem 是 上传文件的流类型 => 对文件进行保存 //是字段类型 => 获得字段内容. ============================================================= 三个核心类 1.DiskFileItemFactory 用于设置文件上传时,缓冲区大小以及临时文件存储位置. //1.1 可以设置文件上传缓冲区大小 factory.setSizeThreshold(1024*1024); //设置为1m 默认是10k //1.2可以设置临时文件存储位置 File temp=new File(this.getServletContext().getRealPath("/temp")); factory.setRepository(temp); //可以指定临时文件存储位置,默认是系统的临时文件存储位置 2.ServletFileUpload 它的作用是真正完成解析数据操作上传类 1.pareRequest(HttpServletRequest request) 得到所有的上传信息,将每一部分映射成FileItem对象. 2.isMultipartContent(HttpServletRequest request) 这个方法返回值是boolean,它是用于判断当前表单是否是一个上传的表单, 简单说,就判断它的encType的值是否是 multipart/form-data. 3.setHeaderEncoding(String encoding) 用于解决上传文件名称中文乱码问题 4.可以设置上传文件大小,如果超过设置大小.将会抛出异常(默认没有最大值) void setFileSizeMax(long fileSizeMax) 设置单个文件上传大小 void setSizeMax(long sizeMax) 设置总文件上传大小 3.FileItem 它代表的是每一个上传项(其时就是表单中的每一个组件) 1.isFormField() 这个方法返回的是boolean类型, 它是判断当前组件是否是上传组件 简单说,就是判断type="file", 如果返回true,代表不是上传组件,返回false,代表是上传组件 2.getName() 获取非上传组件的上传文件的名称,如果是非上传组件,返回的是null 3.getFieldName() 获取组件名称,提交的键 4.getString() 获取非上传组件的value值, 通过它也可以获取上传的文件内容,但是,使用它获取不合适。 如果使用了commons-fileupload进行文件上传,而上传表单中包含了 非上传组件,获取其值,不能使用request获取. getString()有一个重载的方法 getString(String encoding)可以解决乱码问题 问题:使用getString()去获取上传文件内容不合适,那么怎样操作? 基本操作: 通过FileItem.getInputStream();可以获取一个输入流,这个输入流就可以 读取出上传文件内容。 InputStream is = item.getInputStream(); // 用于读取上传文件内容的输入流. FileOutputStream fos = new FileOutputStream( "d:/upload/" + filename); int len = -1; byte[] b = new byte[1024 * 10]; while ((len = is.read(b)) != -1) { fos.write(b, 0, len); fos.flush(); } fos.close(); is.close(); 可以使用IOUtils工具完成文件copy操作 IOUtils.copy(is, fos); 5.delete方法 它是用于上传完成后,删除临时文件的 ----------------------------------------------- 问题:关于文件上传时文件名称包含中文的乱码问题? 调用ServletFileUpload的setHeaderEncoding方法 ----------------------------------------------- 问题:普通表单字段提交时,中文乱码问题? FileItem的 getString方法返回提交的值.通过参数来设置解码码表 例如: getString("UTF-8"); ----------------------------------------------- 问题: 如何设置上传文件大小限制? 调用ServletFileUpload的setSizeMax(总大小)或setFileSizeMax(每个大小)方法 ------------------------------------------------ 问题:上传文件后,我们应该把文件保存到什么位置? 1.上传后需要其他用户可以直接访问,照片 放到webRoot下. 2.上传后其他用户不能直接访问,CSDN 放到webRoot以外的文件夹. WEB-INF下或硬盘其他位置 .例如 d:/xxx ----------------------------------------------------------------------------------- 问题: 上传文件时,该使用什么名字将文件保存? 文件名称不能使用用户命名的名称. 用户命名的名称我们需要保存到数据库中,在下载时使用. 不是用用户命名的名称,我们以什么名称保存文件(不能重复)? 1.UUID 2.登录用户名+当前系统毫秒数 如何获得用户命名的文件名? getName方法即可获得文件名. IE浏览器中,会把文件的在客户端的完整路径传过来.需要截取. 其他浏览器只会文件名称传过来.直接使用,无需截取. ----------------------------------------------------------------------------------- 问题:为了防止同一个目录下方上传文件数量过多,思考如何解决? 1> /upload/2015/07/22/xxxx 使用当前日期作为子文件夹名称 2> 当前登录用户的用户名作为文件夹名称 ============================================================================ 多文件上传 原理: 在form中添加多个type="file"的input即可. 实现: 使用JS实现,动态添加多个type="file"的input. =================================================================================================== 3.文件下载 文件下载方式 1. 直接将待下载文件放到webRoot文件夹或子文件夹下. 2.需要控制资源的下载.在下载前要经过逻辑处理. 将资源放到用户不能直接访问的地方. 例如: WEB-INF 或 d:/upload ------------------------------------------------------------------------------------ 下载编码问题: 1. 如何使用一个servlet 提供多个文件的下载 使用参数传递下载的文件名称 2.客户端的超连接中如果包含了中文,会出现get请求方式乱码问题 <a href="${pageContext.request.contextPath}/download?filename=天空.mp3">下载王非天空.mp3</a> String filename = request.getParameter("name"); // yog.rar / 她说.mp3 byte[] b = filename.getBytes("ISO-8859-1"); filename = new String(b,"UTF-8"); 实际上Get提交时包含中文乱码的解决。 3.关于下载文件名称中文乱码问题 response.setHeader("content-disposition", "attachment;filename="+ filename); 这段代码中的filename是指定下载文件时的名称 ------------------------------------------------------------------------------------------------------------------- 注解 annotation 什么是注解?它有什么作用? 注解就是 @xxx 这样的东西就是注解. 注释:给程序员看的. 注解:给程序看。 使用注解的目的: 其实将来使用注解目的就是为了代替传统配置文件. ------------------------------------------------ jdk中提供的三个注解 1.@Override 它是用来描述当前方法是一个重写的方法. 作用:在编译阶段对方法进行检查 注意事项: jdk1.5: 它只能描述继承中的重写 jdk1.6: 它可以描述接口实现的重写,也能描述类的继承的重写 2.@Deprecated 它是用于描述当前方法是一个过时的方法. 问题:为什么描述这个方法过时了? 在旧的版本中的方法在新的版本中已经有了更好的实现, 旧的版本中的方法存在安全隐患,不建议使用时,这样的方法就可以标注成过时方法。 3.@SuppressWarnings("all") 对程序中的警告去除。 @SuppressWarnings("all")去除所有警告. @SuppressWarnings("unused")去除未被使用的变量的警告. @SuppressWarnings("null")可能出现空指针的警告. ---------------------------------------------------------- 自定义注解 通过上面的三个注解的源代码可以发现,要声明一个注解通过 @interface 声明一个注解格式 @interface 注解名{} 分析一下注解的本质: 将其.class文件找到,反编译. @interface MyAnnoation{} 反编译后的结果 interface MyAnnotation extends Annotation { } 结论:注解本质上就是一个接口。它扩展了java.lang.annotation.Annotation接口; 在java中所有注解都是Annotation接口的子接口。 注解也是jdk1.5的一个新特性. ---------------------------------------- 注解的成员 注解本质上就是一个接口,那么它也可以有属性和方法。 但是接口中的属性是 static final的,在注解中注解没有什么意义。 在开发中注解中经常存在的是方法。而在注解中叫做注解的属性. 注解的属性的类型: 1.基本类型 2.String 3.枚举类型 4.注解类型 5.Class类型 6.以上类型的一维数组类型 关于注解的属性声明后的使用: 1.如果一个注解有属性,那么在使用注解时,要对属性进行赋值操作. 例如:@MyAnnotation3(st = "aaa") 2.如果一个注解的属性有多个,都需要赋值,使用","分开属性. @MyAnnotation3(st = "aaa",i=10) 3.也可以给属性赋默认值 double d() default 1.23; 如果属性有默认值,在使用注解时,就可以不用为属性赋值。 4.如果属性是数组类型 1.可以直接使用 属性名={值1,值2,。。。}方式,例如 @MyAnnotation3(st = "aaa",i=10,sts={"a","b"}) 2.如果数组的值只有一个也可以写成下面方式 @MyAnnotation3(st = "aaa",i=10,sts="a") 注意sts属性它是数组类型,也就是说,只有一个值时,可以省略"{}" 5.对于属性名称 value的操作. 1.如果属性名称叫value,那么在使用时,可以省略属性名称 @MyAnnotation3("hello") 2.如果有多个属性,都需要赋值,其中一个叫value,这时,必须写属性名称 @MyAnnotation3(value="hello",i=10) 3.如果属性名称叫value,它的类型是数组类型. 1.只有这个value属性 可以直接赋值,不能写属性名称,但是,如果只有一个值 @MyAnnotation3({"abc"})或 @MyAnnotation3("abc") 但是如果有多个值 @MyAnnotation3({"abc","def"}) 2.如果有多个属性,属性名称叫value 所有属性都需要赋值,那么必须写属性名称. -------------------------------------------------------------------------------------- 1、元注解 元注解是指注解的注解。包括 @Retention @Target @Document @Inherited四种。 1.1、@Retention: 定义注解的保留策略 @Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含 @Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得, @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到 1.2、@Target:定义注解的作用目标 @Target(ElementType.TYPE) //接口、类、枚举、注解 @Target(ElementType.FIELD) //字段、枚举的常量 @Target(ElementType.METHOD) //方法 @Target(ElementType.PARAMETER) //方法参数 @Target(ElementType.CONSTRUCTOR) //构造函数 @Target(ElementType.LOCAL_VARIABLE)//局部变量 @Target(ElementType.ANNOTATION_TYPE)//注解 @Target(ElementType.PACKAGE) ///包 由以上的源码可以知道,他的elementType 可以有多个,一个注解可以为类的,方法的,字段的等等 1.3、@Document:说明该注解将被包含在javadoc中 1.4、@Inherited:说明子类可以继承父类中的该注解 ---------------------------------------------------------------------------------- 自定义注解要有功能,需要结合反射去完成操作. 可以使用注解来替换配置文件. 案例:银行最大转账金额. 注解使用---让注解具有功能,需要结合反射来完成. 1.创建一个注解 BankInfo,它具有一个属性 maxMoney类型是double类型. 2.添加两个元注解来描述注解是在runtime阶段有效果,并且是应用在方法上的. @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface BankInfo { double maxMoney(); } 3.在银行转账的方法上使用这个注解 @BankInfo(maxMoney=30000) public void acccount(String name1, String name2, double money) 4.在account方法中,获取注解上的maxMoney属性值. 要结合反射来完成 1.在这个方法中获取本方法的Method对象 2.通过Method类中的getAnnotation(Class c) 参数就是注解类型的Class对象
|
|
来自: Dragon_chen > 《javaee和mysql》