【黑马程序员】第12课:文件上传&文件下载&注解

<pre>

day12

上节内容回顾

1、jstl的标签

*if  choose

*forEach

<c:forEachvar="l" items="${list}">

2、jsp开发模式

*模型一

*模型二(mvc模式)

**mvc模式

***m:模型,使用javabean

***v:视图,使用jsp

***c:控制器,使用servlet

*dao模式:数据访问对象,专注于对数据库的操作

**首先创建接口,在接口里面定义操作数据库的方法

**其次,创建类实现这个接口里面的方法

*javaee三层结构:web层、业务逻辑层、持久化层

3、使用mvc+dao模式案例

思维导图

1、文件上传

(1)什么是文件上传:把本地的文件上传到服务器上,比如网盘应用

(2)实现文件上传,在servlet里面没有实现上传的技术,要想实现文件的上传使用到第三方的技术。

(3)使用的上传的技术常用的包含两种:

第一种:jspsmartupload:适用于模型一,嵌入JSP中的组件,会有Java代码。

第二种:fileupload:适用于模型二(mvc),

FileUpload是 Apache commons下面的一个子项目,组件FileUpload依赖于Commons IO组件

*使用fileUpload组件需要导入jar包(两个jar包)

(4)如何实现文件的上传?

三个基本要求

第一个要求:在页面中需要有一个表单,表单的提交方式需要是post方式

第二个要求:在表单里面,需要有一个文件上传项,在文件上传项里面必须要有name属性

<inputtype="file" name="filename"/>

第三个要求:在form表单里面,设置一个属性enctype的值 multipart/form-data

关于enctype属性在一般情况下不需要做任何的设置,只是在做文件上传的时候才需要使用到这个属性

=<form action="/day12/upload" method="post"enctype="multipart/form-data">

*创建一个页面,在页面里面写表单,表单里面写普通输入项和文件上传项,提交到一个servlet里面,查看执行过程。

(5)使用代码实现文件的上传(使用fileUpload组件实现文件的上传)

*实现上传的步骤是固定的

第一步:创建一个磁盘文件项工厂

**使用DiskFileItemFactory类,new DiskFileItemFactory()创建工厂

第二步:创建一个核心的上传类

**使用ServletFileUpload类,new ServletFileUpload(FileItemFactory fileItemFactory)

第三步:使用核心上传类解析request对象

**使用ServletFileUpload类里面的方法parseRequest(javax.servlet.http.HttpServletRequest request)

**返回的是list集合,在集合里面有泛型是FileItem,

***在提交的表单里面,可能有普通输入项和文件上传项,会有多个,每个都是使用FileItem,多个项构成

了一个list集合

第四步:返回list集合,判断普通输入项还是文件上传项

**遍历list集合,判断普通输入项还是文件上传项 isFormField()

第五步:如果是普通输入项,获取输入的值;如果是文件上传项,写上传的代码

**代码

//得到上传文件的名称

Stringfilename = fileItem.getName();

//使用getName方法得到文件名称,在某些浏览器下面得到的带路径地址 c:\test\1.txt

intlens = filename.lastIndexOf("\\");

//判断

if(lens!= -1) {

//截取的操作

filename= filename.substring(lens+1);

}

//把表单提交过来的文件写到服务器路径下面

//使用输入流得到提交过来的文件

InputStreamin = fileItem.getInputStream();

//得到upload的完全路径

Stringpath = getServletContext().getRealPath("/upload");

OutputStreamout = new FileOutputStream(path+"/"+filename);

//流对接

intlen = 0;

byte[]b = new byte[1024];

while((len=in.read(b))!=-1){

out.write(b,0, len);

}

in.close();

out.close();

(6)核心api的使用

*DiskFileItemFactory:磁盘文件项工厂

**构造方法

=DiskFileItemFactory()

*设置缓冲区的大小和临时文件存储路径

==设置缓冲区的大小:setSizeThreshold(int sizeThreshold)

==临时文件存放的路径:setRepository(java.io.File repository)

=DiskFileItemFactory(int sizeThreshold, java.io.File repository)

*第一个参数:上传时候有缓冲区,设置缓冲区的大小(单位字节)

*第二个参数:上传文件超过缓冲区的大小,产生临时文件,临时文件存放的路径

*ServletFileUpload:核心上传类

=parseRequest(javax.servlet.http.HttpServletRequest request):返回list集合,list集合的泛型是FileItem

=setFileSizeMax(long fileSizeMax):设置单个上传文件的大小(单位字节)

=setSizeMax(long sizeMax):设置所有上传文件的总的大小

*当上传的文件超过设置的大小,抛出异常:The field filename exceeds its maximum permitted  size of 1048576 characters.

=setHeaderEncoding(java.lang.String encoding):设置上传文件名称中文编码

*FileItem

**是一个接口

**方法

=getFieldName():获取表单输入项的name的值,返回string类型

=getString():获取普通输入项的值

=getString(java.lang.String encoding):获取普通输入项的值,解决输入项里面中文的乱码

*参数:设置输入值的编码

=boolean isFormField():判断是普通项还是文件上传项,返回true表示是普通项,返回false表示是文件上传项

=getInputStream() :获取通过表单提交过来的文件的输入流

=String getName():获取上传的文件的名称

*在某些浏览器下面,得到带里面的文件比如c:\text/1.txt

*想要的具体的文件名,截取字符串

=delete():当上传文件超过缓冲区大小产生临时文件,删除临时文件

(7)上传过程中产生的问题

*现在上传了一个文件名称1.txt,第二次再上传一个相同名称的文件 1.txt

*最后上传的文件会把之前的文件覆盖

*解决方法:

**在上传的文件名称里面添加一个随机的唯一的字符串

***如何生成随机的字符串 UUID

//生成随机字符串

Stringuuid = UUID.randomUUID().toString();

filename= uuid+"_"+filename;

**了解:根据文件的内容,计算文件内容的md5值,把文件的md5值存到数据库里面。

第二次上传文件,首先得到文件的md5值,拿着md5的值到数据库查看是否有相同md5,如果有,表示文件内容的相同,

,不需要再保存一份文件,直接返回文件名称。

2、文件下载

(1)什么是文件的下载:从服务器上把文件存到本地的硬盘

(2)如何实现文件的下载

*有两种方式

第一种:使用超链接实现下载

**创建一个页面,在页面上创建一个超链接,超链接的地址要下载的文件的完全路径

***使用超链接这种方式不好,不是所有的格式的文件都提示下载,如果图片的格式,直接打开

第二种:写java代码实现下载(****)

*实现步骤:

第零步:设置要下载的文件的mime类型浏览器

**String type = getServletContext().getMimeType(filename);

response.setContentType(type);

第一步:设置头信息Content-Disposition(无论什么格式都会提示下载)

第二步:使用输入流得到要下载的文件

**InputStream in = new FileInputStream(path);

第三步:使用输出流把文件流写到浏览器

**输出流 response.getOutputStream();

第四步:流对接,最后关闭流

(3)如果要下载的文件名称包含中文,会乱码问题

*如果想要得到当前请求的浏览器:使用头信息 User-Agent,request.getHeader("User-Agent");

*不同的浏览器需要不同的编码,ie采用url编码,火狐采用base64编码

*判断不同的浏览器,不同的浏览器采用不同的处理方式

=============================================================

上午内容的总结

(1)掌握如何使用代码实现文件的上传

*上传的三个要求

*上传步骤

*文件重名问题的解决方法

(2)掌握如何使用代码实现文件的下载

==================================================================

(3)如果要下载的文件名称包含中文,会乱码问题

*如果想要得到当前请求的浏览器:使用头信息 User-Agent,request.getHeader("User-Agent");

*不同的浏览器需要不同的编码,ie采用url编码,火狐采用base64编码

*判断不同的浏览器,不同的浏览器采用不同的处理方式

解决方法:

首先,得到请求的浏览器的类型 User-Agent

其次,根据火狐和ie进行不同的处理

=代码

//得到当前的请求的浏览器的类型

Stringagent = request.getHeader("User-Agent");

//区别不同的浏览器

if(agent.contains("Firefox")){//如果是火狐浏览器

//火狐采用的base64编码

filename= "=?UTF-8?B?"+

new BASE64Encoder().encode(filename.getBytes("utf-8"))+"?=";

}else {

//ie采用的url编码

filename= URLEncoder.encode(filename, "utf-8");

}

3、练习一:使用js控制多文件的上传

*画图分析实现的效果

*需求的描述:

**创建一个页面,在页面上创建两个按钮,一个是上传,一个是增加

**每次点击增加按钮,在按钮下面添加一个文件上传项和删除按钮

**点击每次生成的删除按钮,把删除按钮所在的那一行删除

**点击上传按钮,会把所有文件上传项里面的文件传递服务器

=代码

//增加文件上传项和删除按钮<input type="file" name="filename"/><inputtype="button" value="删除"/>

function add1() {

//得到div

var div1 =document.getElementById("div1");

div1.innerHTML +="<div><input type=‘file‘ name=‘filename‘/><inputtype=‘button‘ value=‘删除‘ onclick=‘deldiv(this);‘/></div>";

}

//删除一行文件上传项和删除按钮

function deldiv(who) {

//最终目的,把删除按钮所在的div删除就可以了

//得到删除按钮的父节点 div

var div11 = who.parentNode;

//把div11删除就可以了,但是要通过父节点删除

var div1 = div11.parentNode;

//使用div1删除div11

div1.removeChild(div11);

}

4、注解

(1)什么是注解:注解是jdk5.0新特性

*jdk5.0里面的新特性:泛型、枚举、增强for循环、可变参数

**增强for循环:底层是使用迭代器实现的

**枚举:在一定范围内,每次只能出现其中的一个

***枚举的定义:使用一个关键字 enum 类名称 {  RED,GREEN; }

**可变参数:可变参数只能使用在方法的参数列表中

publicvoid test11(int...args) {}

可变参数理解为数组

*注解就是代码里面特殊的标记

*语法 @注解的名称

(2)jdk里面的注解有三个注解

第一个注解:@Override,限定重写父类的方法名称

在jdk1.6开始,支持接口和实现类的 使用 @Override

第二个注解:@SuppressWarnings("all"),抑制警告

第三个注解:@Deprecated,表示方法过时

(3)自定义注解

*定义方式: @interface 自定义注解的名称 {

注解上面的属性: 类型 名称();

}

*注解上面的属性的类型:基本数据类型、string、Class、注解、枚举以及这些的一维数组

*在方法上面使用:

=代码

@myanno(aa="bbbb",m=1,clazz=TestAnno02.class,[email protected],c1=Color.RED,arr={"cc","dd"})

publicvoid run1() {}

=代码

@interface  myanno {

//定义string类型的属性

Stringaa();

//定义一个int类型的属性

intm();

//定义Date类型的属性

/*

* Invalid type Date for the annotationattribute myanno.date;

* only primitive type, String, Class,annotation, enumeration are permitted or 1-dimensional arrays thereof

* */

//Datedate();

//Class类

Classclazz();

//注解

my1my();

//枚举的属性

Colorc1();

//数组的属性

String[]arr();

}

(4)特殊的注解

*定义注解的属性时候,如果属性的名称是value,表示特殊的注解

*使用这个注解的时候,属性的名称可以不写

=代码

//创建自定义注解

@interfaceMy11 {

Stringvalue();

}

@My11("aa")

publicvoid test1() {}

5、内容补充:JUnit单元测试

(1)测试:单元测试、集成测试、系统测试

**压力测试、性能测试。。。。

(2)什么是单元测试:针对的是一个类里面的某个方法(测试方法的)

*JUnit就是一个单元测试的框架,不需要写main方法,可以直接运行类里面的某个方法

*junit不是jdk的一部分,使用需要导包,但是myeclipse工具自带包,可以直接导入

(3)使用junit单元测试

*使用注解的方式进行测试,如果要某个方法去执行,在这个方法上面添加一个注解 @Test

*运行这个方法:选中这个方法,右键点击run as--> junit test,可以运行这个方法

**运行之后,出现一个绿色条,表示测试通过了

**运行之后,出现一个红棕色条,表示测试没有通过

*如果类里面有多个方法要进行单元测试,点击类里面任意的位置,run as--> junit test,

可以把类里面添加了@Test 注解的方法运行

*另外的一个注解 @Ignore,让某个方法不参与单元测试

*反射:得到Class类,有三种

*得到类里面的方法:getMethods得到所有的方法,得到某一个方法使用 getMethod

*得到方法,让方法去执行,使用 invoke(Object obj, Object... args)

6、练习二:使用自定义注解+反射模拟单元测试的效果

*自定义一个注解 @MyTest ,把这个注解写到某个方法上面,执行让这个方法去执行

*自定义注解,自定义注解默认只是在源代码阶段有效,设置使用范围,使用元注解

@Retention(RetentionPolicy.RUNTIME)

RetentionPolicy.CLASS:编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解. 这是默认值

RetentionPolicy.RUNTIME:编译器将把注释记录在class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注释

RetentionPolicy.SOURCE:编译器直接丢弃这种策略的注释

=代码

@Retention(RetentionPolicy.RUNTIME)

[email protected] MyTest {

}

=代码

/*

* 首先得到类里面的所有的方法

*   ** 使用反射得到类里面的所有的方法

* 其次得到有注解的方法

* 第三让带注解的方法执行

* */

publicstatic void main(String[] args) {

//让TestJunit02类里面带注解MyTest的方法执行

//得到Class类

Classclazz = TestJunit02.class;

//得到TestJunit02类里面的所有的方法

Method[]methods = clazz.getMethods();

//遍历数组

for(Method method : methods) {

//判断类里面的方法是否有注解

boolean flag =method.isAnnotationPresent(MyTest.class);

/*

* 自己定义的注解,这个注解有使用范围,在默认的情况下,范围只是在源代码阶段有效

* 在编译之后class里面还有注解,使用 元注解,设置使用范围

* */

//                         System.out.println(flag);

//得到方法里面带注解的方法

if(flag){

//让方法执行

try{

method.invoke(clazz.newInstance());

}catch (Exception e) {

e.printStackTrace();

}

}

}

}

7、练习三:使用注解完成数据库的查询的操作

*把数据库的一些连接的信息定义到注解的属性里面,在方法里面得到属性的内容,完成数据库的操作

*使用传统方式实现查询数据库的操作

*掌握如何获取自定义注解上面的属性值

=代码

//使用反射获取自定义注解里面的属性的值

Classclazz = TestJDBC02.class;

//得到注解所在的方法

Methodm1 = clazz.getMethod("selectUser");

//得到方法上面的注解

JdbcInfoinfo = m1.getAnnotation(JdbcInfo.class);

//得到注解里面的属性

Stringdrivername = info.drivername();

Stringurl = info.url();

Stringusername = info.username();

Stringpassword = info.password();

=============================================================

今天内容的总结

(1)文件上传

*掌握代码实现文件上传的操作

**上传三个要求

**代码实现的步骤

*掌握核心api里面的方法

*掌握解决相同的文件名的问题

(2)文件下载

*掌握文件下载的两种方式

*重点掌握代码实现文件的下载

**设置mime类型

**设置头 Content-Disposition

*掌握如果下载的文件名称包含中文解决方法

**使用User-Agent判断不同的浏览器

(3)注解

*掌握jdk里面的三个注解

*掌握自定义注解

**自定义注解里面属性类型只能是基本数据类型,string,Class,枚举,注解,一维数组

*掌握练习:使用注解+反射模式单元测试效果

**自定义注解的使用范围:源代码阶段,使用元注解设置 @Retention(RetentionPolicy.RUNTIME)

*掌握如何获取注解上面的属性值(反射获取)

*把文件上传和下载的代码至少写两遍

*使用注解+反射模式单元测试效果代码至少写一遍

</pre>

【黑马程序员】第12课:文件上传&文件下载&注解

时间: 2025-01-16 04:18:23

【黑马程序员】第12课:文件上传&文件下载&注解的相关文章

黑马程序员---网络编程之文件上传

------- android培训.java培训.期待与您交流! ----------. 网络编程 (1)用编程语言来实现计算机的资源共享和信息传递. 计算机网络:多台独立的计算机用网络通信设备连接起来的网络.实现资源共享和数据传递. (2)网络通信的三要素 A:IP地址 计算机在网络中的唯一标识. 现在使用的是:"点分十进制" B:端口 应用程序的的标记. C:协议 通信的规则. UDP:不建立连接,数据打包传输,数据有限制,数据不可靠,速度快. TCP:建立连接,数据无限制,数据可

黑马程序员_Java基础加强(上)

1.静态导入 静态导入是jdk1.5版本以后出现的新特性,一般是指导入静态方法,如:import static java.lang.System.out 是指导入系统输出的静态方法. 例: import static java.lang.System.out //导入java.lang包下的System类的静态方法out public class StaticImport { public static void main(String[] args) { int x=1; x++; out.p

Selenium第16课 文件上传下载

一.PyKeyboard方法 from pykeyboard import PyKeyboard from pymouse import PyMouse k = PyKeyboard() # k.press_key(k.enter_key) # k.release_key(k.enter_key) k.tap_key(k.enter_key)  # 下载文件时点击enter键 二.浏览器配置 浏览器设置下载时不弹窗:about:config --> browser.download.folder

struts2文件上传/文件下载

文件上传 1 import java.io.File; 2 3 import org.apache.struts2.ServletActionContext; 4 5 import com.opensymphony.xwork2.ActionSupport; 6 7 public class Upload2Action extends ActionSupport { 8 9 private String username; 10 private File[] photo; 11 12 priva

文件上传&amp;文件下载

一.单个文件上传 文件上传需要两个jar包: 首先制作一个简单的页面,用于实现文件上传 <h1>单个文件上传</h1> <s:form action="upload.action" enctype="multipart/form-data" method="post" namespace="/"> <s:textfield name="title" lable=&q

黑马程序员 C语言多文件对团队开发问题

多文件团队开发问题 团体合作在今天很重要,进入公司就需要如何协作分工,比如,微信软件,有人编写登录:有人实现朋友添加功能:有人负责朋友圈等等,这样的大型的软件开发,多个人编写一个程序情况下,是不行的.会有许多问题.对这样问题解决就出现了多文件共同开发.大家通力合作,各做各的功能,最后把它们连接起来.实现整体功能.今天看了个多文件t团队开发,这里边说的是张三只做main()函数,李四做函数声明.张三计算成绩的平均值时,就调用李四编写的平均值函数.张三.c文件的main()函数. #include<

黑马程序员——IO——读取一个文件中的文字输出到控制台上

读取一个文件中的文字输出到控制台上 import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; //读取一个文件中的文字 ,输出到控制台上 //读取的是字符文字,因此可以使用字符流来操作 public class FileReaderDemos { public static void main(String[] args) { // TODO Auto-generate

黑马程序员-JAVA学习之文件夹的复制和遍历所有文件

--------android培训.java培训.期待与你交流!-------- JAVA的文件夹复制由于不知道文件夹里面有多少文件夹,所以使用递归方法遍历里面的所有文件夹和文件,如果是文件,则直接复制到目标文件夹,如果是文件夹,则的目标地方创建对应的同名文件夹,由于文件有各种各样的类型,比如视频,文档,图片等.所以要用到的主要是字节流对象,而不是用字符流对象,在这里用到的几个类分别是 1.File类,文件和目录路径名的抽象表示形式.(即表示既可以是一个文件,也可以是一个文件夹,是一个有分隔符的

struts2实验02 单文件上传, 多文件上传, 文件下载

1.IDEA创建一个maven项目, 项目结构为: . ├── FileUpload.iml ├── pom.xml ├── src │   └── main │   ├── java │   │   └── shiyanlou │   │   └── struts │   │   ├── DownloadAction.java │   │   ├── MultiUploadAction.java │   │   └── UploadAction.java │   ├── resources │