Servlet(Request.Response)+文件上传

 

1. Servlet简介

1.1. 什么是Servlet

(1) servlet是运行在Web服务器中的小型Java程序。 
(2) servlet通常通过HTTP(超文本传输协议)接收和响应来自Web客户端的请求。

1.2. 实现Servlet

(1) 实现Servlet接口 
如果实现接口,需要把接口里面的方法都实现。 
(2) 继承GenericServlet, HttpServlet类 
如果继承类,不需要把类中的方法都实现。 
(3) 需要web服务器知道Java程序不是一个普通的java程序,而是一个servlet 
通过配置进行操作,在web项目中,web.xml里面进行配置。

1.3. Servlet的入门程序

写一个servlet,实现向页面输出内容hello servlet 
第一步,创建一个类,使用这个类继承GenericServlet类; 
第二步,实现类里面的service(ServletRequest req,ServletResponse res); 
       * ServletRequest代表请求 
       * ServletResponse代表响应 
第三步,在Servlet中使用ServletResponse对象向页面输出内容。调用getWriter()方法; 
第四步,在web项目中的web.xml进行配置,让服务器知道是一个servlet

<servlet>
    <servlet-name>servletDemo1</servlet-name>
    <servlet-class>com.gaogao.servlet.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>servletDemo1</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

2. Servlet的执行过程

(1) 根据在浏览器地址栏输入的地址,找web.xml中相同的url-pattern; 
(2) 找到了url-pattern,对应的servlet-name; 
(3) 根据找到的servlet-name到另外一个标签里面(servlet)相同名称的servlet-name; 
(4) 在servlet标签里面找到了相同名称的servlet-name,找servlet的包类路径servlet-class; 
Servlet其实是利用反射原理,让servlet里面的service()方法执行。 
这里写图片描述

servlet的生命周期:从servlet创建到servlet销毁的过程。 
在servlet接口里面有五个方法,其中有三个方法是与生命周期相关的方法: 
(1) init()方法,在servlet创建时候执行这个方法,执行一次,servlet在第一次访问时候创建。 
(2) service()方法,在每次访问servlet时候会执行这个方法,执行多次。 
(3) destroy()方法,销毁servlet时候执行这个方法,执行一次。

4. Servlet开发细节的问题

4.1. HttpServletRequest和ServletRequest关系&HttpServletResponse和ServletResponse关系 
servletRequest和serlvetResponse不带协议 
HttpServletRequest和HttpServletResponse带协议 
sun公司设计时候,认为未来互联网的发展有很多的协议,目前只有http协议。

4.2. GenericServlet类两个init方法

查看源码,发现有参数init方法最终也要调用init没有参数的方法,直接使用init没有参数的方法就可以了。

4.3. HttpServlet类里service和doxxx关系

根据提交的方式,调用不同的doXX的方法,比如提交方式是get,调用doGet方法,比如提交方式是post,调用doPost方法; 
一般在开发中,直接写doGet和doPost方法就可以了; 
一般在创建servlet时候,直接继承HttpServlet实现servlet。

4.4. 服务器启动时候创建servlet

通过配置文件进行配置,在servlet标签里面写标签:

<load-on-startup>正整数的值</load-on-startup>
  •  

4.5. 简化编程

当通过get提交方式时候,实现从1加到100; 
当通过post提交方式时候,实现从1加到100; 
无论什么提交方式,代码都能执行到,在dopost方法里面调用doget方法。

5. url-pattern的配置

5.1. 配置有三种方式

第一种方式:完全路径匹配,写法 :/aa/hello 
第二种方式:目录匹配,写法:/aa/* 
第三种方式:扩展名匹配,写法: *.do, *.action

5.2. 优先级

完全路径匹配 > 目录匹配 > 扩展名匹配

5.3. 练习

对于如下的一些映射关系: 
Servlet1 映射到 /abc/* 
Servlet2 映射到/* 
Servlet3 映射到 /abc 
Servlet4 映射到 *.do 
问题: 
1、当请求URL为"/abc/a.html""/abc/*""/*"都匹配,哪个servlet响应? 
Servlet1 
2、当请求URL为"/abc"时,"/abc/*""/abc"都匹配,哪个servlet响应? 
Servlet3 
3、当请求URL为"/abc/a.do"时,"/abc/*""*.do"都匹配,哪个servlet响应? 
Servlet1 
4、当请求URL为"/a.do"时,"/*""*.do"都匹配,哪个servlet响应? 
Servlet2 
5、当请求URL为"/xxx/yyy/a.do"时,"/*""*.do"都匹配,哪个servlet响应? 
Servlet2

6. 开发中路径的问题

6.1. 相对路径

在html文件中引入图片: 
第一种:图片和html在同一个目录下面,直接写图片的名称 
第二种:图片在html的上层目录, 写 ../ 表示上层目录 
第三种:图片在html的下层目录, 直接写目录名称和图片名称

6.2. 绝对路径(一般开发中都使用)

第一种写法:http://ip地址+端口号/文件的路径 
<img src="http://127.0.0.1/day07-3/path02/a.jpg"/> 
第二种写法:直接写 /项目名称/文件路径 
<img src="/day07-3/path01/cc/c.jpg"/>

7. 请求重定向和请求转发

7.1. 请求重定向

(1) 使用的是客户端路径 
(2) 重定向请求两次,使用的是客户端路径,携带项目名称,比如/day07/demo3 
这里写图片描述 
请求重定向可以使用一下两种方式: 
a) 设置状态码302+头信息Location实现重定向操作 
b) 使用response.sendRedirect()实现重定向操作

public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
        //得到输入的用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //根据用户名和密码判断,(用户名admin、密码123456),判断正确则向页面输出login success内容
        if("admin".equals(username) && "123456".equals(password)) {
            //向页面输出内容
            response.getWriter().write("login success");
        } else { 
            //重定向到登录页面
            //设置状态码
//          response.setStatus(302);
            //使用头Location完成重定向
//          response.setHeader("Location", "/day08-1/login.html");
            //简写方式
            response.sendRedirect("/day08-1/login.html");
        }
    }
    public void doPost(HttpServletRequest request,HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

定时跳转的案例

public class RefreshServlet extends HttpServlet {
    /**
     * 定时跳转
     */
    public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
        //使用头信息Refresh实现,表示5秒后跳转到指定的url路径
        response.setHeader("Refresh", "5;url=/day08-1/login.html");
        //提示
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("将在5秒之后跳转到登录页面");
    }
    public void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
        doGet(request, response);
    }
}

7.2. 请求转发

(1) 使用的是服务端路径 
(2) 转发请求一次,使用的是服务器端路径,不需要携带项目名称,比如/demo4 
这里写图片描述 
示例代码:

public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
        //获取表单提交的用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //判断 用户名 admin,密码 123456
        if("admin".equals(username) && "123456".equals(password)) {
            //登录成功
            response.getWriter().write("login success");
        } else {
            //登录失败,给request设置域属性msg,并且转发到登录页面,并且将错误信息传递过去
            request.setAttribute("msg", "用户名或者密码错误");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        doGet(request, response);
    }
}

8. ServletConfig对象

8.1. 获取ServletConfig对象

直接使用方法创建对象getServletConfig()。

8.2. 得到当前运行的servlet的名称

(1)web.xml中<servlet-name>ConfigDemo1</servlet-name> 
(2)String getServletName()

8.3. 创建servletContext对象

(1)ServletContext getServletContext() 
(2)一般都使用getServletContext()方法

8.4. 获取初始化参数

(1)在web.xml中进行配置初始化参数 
在servlet标签里面进行配置 
(2)String getInitParameter(String name) :根据名称得到值(参数是初始化参数名称) 
代码:

//得到servletconfig对象
ServletConfig config = getServletConfig();
//getInitParameter(String name)
String username = config.getInitParameter("username");
String password = config.getInitParameter("password");

(3)Enumeration getInitParameterNames() :得到所有的初始化参数的名称 
代码:

//得到servletconfig对象
ServletConfig config = getServletConfig();
//得到所有的初始化参数名称
Enumeration<String> enumrEnumeration =config.getInitParameterNames();
//得到每个参数的名称
while(enumrEnumeration.hasMoreElements()) {
    String name = enumrEnumeration.nextElement();
    //根据name得到值
    String value = config.getInitParameter(name);
    System.out.println(name+" :: "+value);
}

9. ServletContext对象

9.1. 创建ServletContext对象

第一种方式,使用ServletConfig对象里面的方法 getServletContext() 
第二种方式,直接使用 getServletContext()

9.2. 获取全局的初始化参数

(1)配置全局初始化参数

<context-param>
    <param-name>url</param-name>
    <param-value>localhost</param-value>
</context-param>

(2)String getInitParameter(String name),根据名称得到全局初始化参数的值:

//得到servletContext对象
ServletContext context = getServletContext();
//根据名称得到全局初始化参数的值
String url = context.getInitParameter("url");
String name = context.getInitParameter("name");

(3)Enumeration getInitParameterNames(),得到所有的全局初始化参数的名称:

//得到servletContext对象
ServletContext context = getServletContext();
//使用方法得到所有的全局初始化参数的名称
Enumeration<String> enumrEnumeration = context.getInitParameterNames();
//得到每个全局初始化参数的名称
while(enumrEnumeration.hasMoreElements()) {
    String name = enumrEnumeration.nextElement();
    String value = context.getInitParameter(name);
    System.out.println(name+" :: "+value);
}

9.3. servletContext域对象

在启动tomcat服务器时候,会为每个项目创建一个servletContext对象,在这个项目里面如果通过servlet1向servletContext里面设置一个值,在这个项目里面的其他的servlet里面都可以获得这个值。 
(1)servletContext域对象:在一定的范围内,存值和取值,范围是整个web项目 
(2)存值:setAttribute(String name, Object object) 
(3)取值:getAttribute(String name) 
(4)首先创建servlet1,通过servlet1向servletContext里面设置一个值,其次,再创建servlet2,在servlet2获取通过servlet1设置的值

9.4. 练习:统计网站的访问次数

创建一个servlet,每次访问这个servlet计算一次访问 
实现的步骤(分析图) 
这里写图片描述

10. ServletContext获取项目资源

10.1. 传统方式获取web项目中的文件

(1)创建web项目,创建properties文件 
(2)得到要操作文件的输入流,使用相对路径 
       * classes/db1.properties : 相对路径 
       * 相对虚拟机的位置 
       * 在web项目中,虚拟机在tomcat启动时候,tomcat在bin里面 
(3)使用传统方式里面的相对路径,不能读取web项目中的文件

10.2. ServletContext读取项目中的文件

(1)InputStream getResourceAsStream(java.lang.String path),得到要操作文件的输入流 
(a)第一个操作:文件放到src下面 
路径:第一个位置/,理解为项目的名称;后面写文件在tomcat的webapps里面的具体的路径 
代码:

InputStream in = context.getResourceAsStream("/WEB-INF/classes/db1.properties");
  •  

(b)第二个操作:文件放到包里面 
路径:第一个位置/理解为项目名称;后面写文件在tomcat的webapps下面的具体的路径

InputStream in= context.getResourceAsStream
("/WEB-INF/classes/cn/itcast/read/db2.properties");

(c)第三个操作:文件放到webroot下面 
路径:第一个位置/理解为项目名称;后面写文件在tomcat的webapps下面的具体的路径 
代码:

InputStream in = context.getResourceAsStream("/db3.properties");

*注意:当把文件放到和webroot同级的目录下面,这个文件不会部署到tomcat里面,所以使用servletContext对里面getResourceAsStream方法不能得到文件的内容。

(2)String getRealPath(java.lang.String path),得到要操作文件的完全路径(带盘符的路径) 
参数:和getResourceAsStream类似的 
第一个位置/,项目名称;后面写文件在tomcat的webapps里面的具体的路径。 
代码:

//使用getRealPath方法
String path = context.getRealPath("/db3.properties");
//C:\Users\asus\Desktop\javaweb\day06\apache-tomcat-7.0.53\webapps\day07-7\db3.properties
//得到要操作文件的输入流
InputStream in = new FileInputStream(path);

11. 类加载器读取文件

读取的文件的位置是 classes里面的文件 
得到类加载器: 
(1)首先得到Class 
       *第一种方式:类名.class 
       *第二种方式:对象.getClass() 
       *第三种方式:Class.forName(“包类路径”)

(2)使用Class得到类加载器 
代码:

//得到类的Class
Class clazz = ServletDemo1.class;
//得到类加载器
ClassLoader loader = clazz.getClassLoader();
//得到要操作文件的输入流
//文件的路径,因为读取的classes里面的文件,直接写文件的名称
InputStream in = loader.getResourceAsStream("db1.properties");

12. 默认的servlet

比如在浏览器的地址栏随便输入一个地址,出现404,资源找不到,这个效果是由默认的servlet实现的。在tomcat的conf里面找到web.xml,有对默认servlet的配置: 
(a)如果自己创建servlet,让这个servlet在启动时候创建,<load-on-startup>大于1的值</load-on-startup> 
(b)默认servlet的配置里面url-pattern是/,当把自己创建的servlet的url-pattern写成/,这个servlet就会成为一个默认的servlet

<servlet>
    <servlet-name>default</servlet-name>
    <servlet-class>
          org.apache.catalina.servlets.DefaultServlet
    </servlet-class>
    <init-param>
        <param-name>debug</param-name>
        <param-value>0</param-value>
    </init-param>
    <init-param>
        <param-name>listings</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

在默认的servlet的初始化参数里面有 listings,当把这个参数的值设置成true之后,当直接访问web项目中文件夹时候,会把文件夹里面的所有内容显示出来。

13. Response和Request

request:代表请求,在浏览器的地址栏输入地址,点击回车,这个过程称为一次请求; 
response:代表响应,服务器端根据客户端的请求,返回数据到浏览器中进行显示,这个过程称为一次响应。

14. Response对象

HttpServletResponse,是一个接口,父接口是ServletResponse,代表响应对象。 
http的响应包含三部分组成: 
(1)第一部分:响应行,响应行中包含了状态码 
常用方法:

方法作用
setStatus(int sc)设置状态码 如response.setStatus(302)

(2)第二部分:响应头 
响应头是key-value结构,一个key可以有一个value,一个key也可以有多个value。 
常用方法:

方法作用
setHeader(java.lang.String name, java.lang.String value)设置响应头
两个参数:第一个参数是响应名称;第二个参数值
setIntHeader(java.lang.String name, int value)针对int类型值的方法
setDateHeader(java.lang.String name, long date)值long类型,是毫秒数(1970 1 1至今的毫秒数)
addHeader(java.lang.String name, java.lang.String value)设置响应头
两个参数:第一个参数是响应名称;第二个参数值
addIntHeader(java.lang.String name, int value)针对int类型值的方法
addDateHeader(java.lang.String name, long date)值long类型,是毫秒数

setHeader和addHeader的区别: 
setHeader会将之前的值覆盖掉,而addHeader可以添加多个响应头。

(3)第三部分:响应体,向页面显示的内容 
常用方法:

方法作用
getWriter()使用字符流向页面输出内容
getOutputStream()使用字节流向页面输出内容

14.1. 重定向的案例

当注册一个网站,注册完成之后,5秒之后跳转到登录页面。 
实现方式:使用头信息Refresh实现

response.setHeader("Refresh","在几秒值后跳转;url=要跳转到页面的路径");

创建servlet,在servlet实现,在五秒之后跳转到一个页面:

response.setHeader("Refresh", "5;url=/day08-1/login.html");

14.2. 设置响应体(向页面输出内容)

14.2.1. 使用字节流向页面输出内容

代码:

response.getOutputStream().write("输出的内容".getBytes());

如果向页面输出中文,根据不同的浏览器的编码设置会产生乱码问题。产生原因:浏览器的编码和字节数组的编码不一致。 
解决方法:让浏览器的编码和字节数组的编码一致 
1、设置浏览器的编码 
2、设置字节数组的编码

//设置浏览器的编码 使用头信息 Content-Type
response.setHeader("Content-Type", "text/html;charset=utf-8");
//设置字节数组的编码
response.getOutputStream().write("字节流中文".getBytes("utf-8"));

14.2.2. 使用字符流向页面输出内容

代码:

response.getWriter().write("response");

如果使用字符流向页面输出中文,一定会有乱码 
原因:使用字符流向页面输出内容;首先会把内容放到response缓冲区里面,response缓冲区默认的编码是 iso8859-1,这个编码不支持中文,一定会有乱码。 
解决方法:response缓冲区的编码和浏览器的编码一致。 
1、设置response缓冲区的编码 
2、设置浏览器的编码

//设置response缓冲区的编码
response.setCharacterEncoding("utf-8");
//设置浏览器的编码
response.setHeader("Content-Type", "text/html;charset=utf-8");
response.getWriter().write("字符流中文");    

14.3. response的流的注意事项

(1)使用字符流向页面输出中文乱码问题解决,简写方式

response.setContentType("text/html;charset=utf-8");
  •  

(2)字节流和字符流是互斥的 
(3)使用字符流不能直接向页面输出数字

//根据数字到码表中查询数字对应的字符,把字符输出
response.setCharacterEncoding("utf-8");
response.getWriter().write(111);

15. 文件下载的案例

(1) 设置头信息 Content-Disposition,无论是什么格式的文件都以下载方式打开 
(2) 在服务器上面有一个可以下载的文件 
(3) 从服务器上拿到这个文件(使用文件输入流得到文件) 
(4) 使用输出流把文件写到浏览器

public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
   // 得到要下载文件的路径
   String path = getServletContext().getRealPath("/down/a.zip");
   // 得到文件的名称
   int lens = path.lastIndexOf("\\");
   String filename = path.substring(lens + 1);
   // 设置头信息
   response.setHeader("Content-Disposition","attachment;filename=" + filename);
   // 得到文件的输入流
   InputStream in = new FileInputStream(path);
   // 使用输出流操作
   OutputStream out = response.getOutputStream();
   // 流对接
   int len = 0;
   byte[] b = new byte[1024];
   while ((len = in.read(b)) != -1) {
     out.write(b, 0, len);
   }
   // 关闭流
   in.close();
}

16. Request对象

request代表请求的对象,HttpServletRequest接口,父接口是ServletRequest。

16.1. 获取请求行的信息

方法作用
getMethod()得到http请求方式
getRequestURI()得到请求地址(不包含ip+端口号)
getProtocol()得到http的版本

16.2. 获取请求头的信息

方法作用
getHeader(java.lang.String name)根据名称得到请求头的值,如:头信息 User-Agent:获取当前请求的浏览器的类型
String agent = request.getHeader(“User-Agent”);

16.3. 获取客户机的信息

方法作用
getContextPath()请求项目的名称
getRequestURL()客户端发送的请求的路径
getRemoteAddr()获取当前客户端的ip地址

16.4. 获取表单提交的数据

(1)String getParameter(java.lang.String name) :参数是表单输入项name属性的值,根据名称得到输入的值 
代码:

String username = request.getParameter("username");
String password = request.getParameter("password");

(2)String[] getParameterValues(java.lang.String name) :参数是表单输入项name的值,针对复选框的情况 
代码:

String[] loves = request.getParameterValues("love");

(3)String[] getParameterValues(java.lang.String name) : 
返回的是map集合,key是表单输入项name属性的值,value是输入的值 
代码:

Map<String,String[]> map = request.getParameterMap();
//得到map集合里面的key和value,遍历map
Set<String> keys = map.keySet();
//遍历set集合
for (String key : keys) {
//根据key得到value
String[] values = map.get(key);
    //key和对应的value输出(表单输入项name的属性值和输入的值)
    System.out.println(key+" :: "+Arrays.toString(values));
}

(4)Enumeration

16.5. 获取表单提交的中文数据乱码问题

(1)post提交方式解决方法 
使用post提交数据时候,会把数据放到request缓冲区里面,request缓冲区默认的编码 iso8859-1,不支持中文。 
解决方法: 
设置request缓冲区的编码 
代码:

request.setCharacterEncoding("utf-8");

(2)get提交中文乱码解决 
有三种方式 
第一种:修改tomcat的配置文件

<Connector port="80" protocol="HTTP/1.1"
     connectionTimeout="20000"
     redirectPort="8443" URIEncoding="utf-8"/>

第二种:把数据先编码,再进行解码 
第三种:使用string构造进行编码,new String(“”); 
代码:

username = new String(username.getBytes("iso8859-1"),"utf-8");

16.6. request是域对象

(1) 域对象:在一定的范围内,可以存值和取值。 
(2) servletContext域对象:范围是整个web项目,存值setAttribute方法和取值getAttribute方法。 
(3) request也是一个域对象:范围是一次请求,存值和取值。 
向request域里面存值的方法:setAttribute(java.lang.String name, java.lang.Object o); 
从request域里面取值的方法:getAttribute(java.lang.String name)。 
(4) request域对象范围是一次请求,经常和转发一起使用 
代码request.getRequestDispatcher(“转发的路径不带项目名称”).forward(..); 
(5) 举例演示request域对象 
创建servlet1,在servlet1里面向request域里面设置一个值,最后转发到servlet2里面:

//向request域里面设置一个值
request.setAttribute("msg", "itcast100");
//转发到servlet2
request.getRequestDispatcher("/servlet2").forward(request, response);

创建servlet2,在servlet2里面获取通过servlet1向request域里面设置的那个值

//获取通过servlet1向request里面设置的值
response.getWriter().write(""+request.getAttribute("msg"));

16.7. 重定向和转发的区别

(1)重定向 
请求次数:重定向请求两次,请求的地址带项目名称 
实现方式:302+Location实现重定向的操作 
实现代码:response.sendRedirect(“路径 带项目名称”);

(2)转发 
请求次数:转发请求一次,路径不需要带项目名称(在服务器内部进行操作) 
实现代码:request.getRequestDispatcher(“转发的路径 不带项目名称”).forward(request, response);

(3)重定向:从一个网站到另外的一个网站 
转发:请求的过程中需要携带数据操作

17. 文件上传

17.1. 什么是文件上传

把本地的文件存储到服务器上,这个过程称为文件的上传。比如,网盘、qq空间。

17.2. 文件上传的实现

(1) jspSmartUpload:应用在jsp的模型一 
适于嵌入执行上传下载操作的JSP文件中 
(2) fileUpload:应用在jsp的模型二(mvc) 
FileUpload 是 Apache commons下面的一个子项目 
组件FileUpload依赖于Commons IO组件 
导入jar包(有两个jar包) 
(3) 要想使用第三方的技术实现文件的上传,首先导入jar包

17.3. 文件上传需要满足的条件

第一个要求:表单,提交方式是post 
get提交方式:地址栏会携带数据,get大小有限制 
第二个要求:在表单里面有文件上传项,必须有name属性 
第三个要求:在form里面,设置一个属性值enctype,设置为multipart/form-data

18. 文件上传的原理的分析(画图)

首先,找到分割线; 
第二,根据分割线区别不同的项; 
第三,普通输入项得到值; 
第四,文件上传项,得到文件的内容,把内容写到服务器里面的一个文件中(使用输入流得到文件的上传内容,使用输出流把文件内的内容写到服务器上) 
这里写图片描述

19. 代码实现文件上传

19.1. 文件上传代码实现的步骤

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

new DiskFileItemFactory();
  • 1

第二步:创建核心上传类

new ServletFileUpload(FileItemFactory fileItemFactory);

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

parseRequest(javax.servlet.http.HttpServletRequest request)
返回的List集合,集合里面有多个FileItem,List<FileItem>

第四步:遍历list集合,得到每个FileItem

第五步:判断是普通输入项还是文件上传项

boolean isFormField()

第六步:如果是普通输入项得到值;如果是文件上传项编写上传的代码 
普输入项:

getFieldName():得到普通输入项name的属性的值
getString():得到普通输入项里面输入的值

文件上传项:

得到通过表单提交过了的文件的输入流,getInputStream()
创建输出流,把文件的输入流写到服务器的一个文件中。

19.2. 代码实现

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // 创建磁盘文件项工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            // 设置缓冲区大小和临时文件路径
            factory.setSizeThreshold(1 * 1024 * 1024); // 字节
            String temp = getServletContext().getRealPath("/temp");
            factory.setRepository(new File(temp));
            // 创建核心上传类
            ServletFileUpload fileUpload = new ServletFileUpload(factory);
            // 设置上传文件名的编码
            fileUpload.setHeaderEncoding("utf-8");
            // 设置上传文件的大小
            // fileUpload.setFileSizeMax(1*1024*1024); //字节
            // 解析request对象
            List<FileItem> list = fileUpload.parseRequest(request);
            // 遍历list集合
            for (FileItem fileItem : list) {
                // 判断普通输入项
                if (fileItem.isFormField()) {
                    // 得到普通输入项的name的属性值和输入的值
                    String name = fileItem.getFieldName();
                    String value = fileItem.getString("utf-8");
                    System.out.println(name + " :: " + value);
                } else {
                    // 得到上传文件的名称 getName()
                    // 在某些浏览器里面,得到的是全路径名称 c:\aa\1.txt
                    String filename = fileItem.getName();
                    // 判断是否带 \,如果带 \进行截取
                    int lens = filename.lastIndexOf("\\");
                    if (lens != -1) {
                        // 截取
                        filename = filename.substring(lens + 1);
                    }
                    // 在文件名称里面添加随机的唯一的值
                    String uuid = UUID.randomUUID().toString();
                    // uuid_filename
                    filename = uuid + "_" + filename;
                    // 得到提交的文件的输入流
                    InputStream in = fileItem.getInputStream();
                    // 得到文件夹的带盘符的路径 ,servletContext对象
                    String path = getServletContext().getRealPath("/upload");
                    // 创建输出流
                    OutputStream out = new FileOutputStream(path + "/" + filename);
                    // 流对接
                    int len = 0;
                    byte[] b = new byte[1024];
                    while ((len = in.read(b)) != -1) {
                        out.write(b, 0, len);
                    }
                    in.close();
                    out.close();
                    // 删除临时文件
                    fileItem.delete();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

20. 核心api的使用

DiskFileItemFactory(int sizeThreshold, java.io.File repository) 
有两个参数: 
第一个参数设置上传文件的缓冲区的大小; 
第二个参数是如果上传文件超出了缓冲区,产生临时文件,设置临时文件路径。 
DiskFileItemFactory() 
setSizeThreshold(int sizeThreshold):设置上传文件的缓冲区的大小 
setRepository(java.io.File repository):设置临时文件路径

20.2. ServletFileUpload

ServletFileUpload(FileItemFactory fileItemFactory)

方法解释
parseRequest(javax.servlet.http.HttpServletRequest request)解析request对象,返回List集合,集合里面每个部分是FileItem。
setHeaderEncoding(java.lang.String encoding)设置上传文件名称的编码
setFileSizeMax(long fileSizeMax)设置单个上传文件的大小
setSizeMax(long sizeMax)设置上传文件的总大小

20.3. FileItem:文件项

方法解释
boolean isFormField()判断是否是普通输入项,返回boolean,如果返回true是普通输入项
getFieldName()得到普通输入项name的属性值
getString()得到普通输入项输入的值
getString(java.lang.String encoding)输入的值有中文,设置编码
getName()得到上传文件的名称。在某些浏览器里面得到带路径的名称,截取操作
getInputStream()得到表单提交的文件的输入流
delete()删除临时文件

21. 文件上传问题的解决

文件重名的问题:如果上传了多个项目名称的文件,最后一次上传的文件,把之后的文件给覆盖了。 
解决方法:在上传的文件名称前面,添加一个随机的唯一的字符串,保证每个文件名称都是唯一的一个值: 
第一种方式:使用当前时间毫秒数实现 
第二种方式:使用UUID工具类实现 
代码:

//在文件名称里面添加随机的唯一的值
String uuid = UUID.randomUUID().toString();
//uuid_filename
filename = uuid+"_"+filename;

转载于:https://my.oschina.net/u/2884845/blog/742763

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值