用 Servlet 进行文件上传的原理和实现
用JSP_Servlet实现文件上传
![用JSP_Servlet实现文件上传](https://img.taocdn.com/s3/m/261bd1ed172ded630b1cb6e6.png)
Stream () ;
int len=request.getContentLength () ;
response.setContentType ( " text/html;
在 B/S 模 式 中 , 文 件 上 传 到 服 务 器 的 操 作 分 为 : request、 打 开 request 中 的 输 入 流 、 生 成 文 件 输出流对象、提取 request 中上传文件的数据等。 1 算法设计
在 B/S 模 式 中 , 浏 览 器 ( Browser) 与 服 务 器 ( Server) 是 请 求 ( request) 和 响 应 ( response) 的 关系。获取来自浏览器端的数据, 主要是通过对 request 进行处理。
文件上传在很多网站应用中是必不可少的, 在 电子商务中上传商品图片, 在音乐网站中上传流行 歌曲……一个高效率的文件上传功能尤为重要。笔 者 主 要 介 绍 用 JSP 方 式 和 Servlet 方 式 实 现 的 两 个 代码简短又高效率的文件上传功能。在此基础上, 可以对文件上传功能进行进一步的完善, 如限制上 传文件的大小、格式, 指定存放路径, 结合数据库 对上传后的文件进行有效的管理等等。
Stream () ;
int len=request.getContentLength () ;
byte [] b=new byte [128] ;
int i=0;
i=in.readLine (b,0,128) ;//读取第一行数据
len- =i;//减去第一行数据的字节数
i=in.readLine (b,0,128) ; //读取第二行数据
同 时 也 能 看 出 最 后 一 行 也 是 “boundary”, 表 示数据结束:
Servlet工作原理
![Servlet工作原理](https://img.taocdn.com/s3/m/a5f41b88db38376baf1ffc4ffe4733687e21fc88.png)
Servlet工作原理Servlet是Java编写的服务器端程序,用于处理客户端请求并生成响应。
它是Java Servlet API的一部份,可以通过Web容器(如Tomcat)来运行。
Servlet工作原理可以分为以下几个步骤:1. 客户端发送请求:当客户端(通常是浏览器)发送一个HTTP请求到服务器时,请求会包含URL、请求方法(GET、POST等)、请求头和请求体等信息。
2. Web容器接收请求:Web容器(如Tomcat)接收到客户端的请求后,会根据URL找到对应的Servlet。
3. Servlet实例化:Web容器会根据Servlet的配置信息,在需要时实例化Servlet对象。
Servlet对象是单例的,即一个Servlet类只会有一个实例。
4. Servlet初始化:Servlet实例化后,容器会调用其init()方法进行初始化。
在初始化过程中,Servlet可以读取配置文件、建立数据库连接等操作。
5. 处理请求:当Servlet初始化完成后,容器会调用其service()方法来处理请求。
service()方法根据请求方法(GET、POST等)的不同,会调用对应的doGet()、doPost()等方法来处理具体的业务逻辑。
6. 生成响应:在处理请求的过程中,Servlet可以通过response对象生成响应内容。
可以设置响应头、写入响应体等。
7. 发送响应:处理完请求后,Servlet会将生成的响应发送回客户端。
响应包括响应状态码、响应头和响应体等信息。
8. Servlet销毁:当Web容器关闭或者重启时,会销毁所有的Servlet实例。
在销毁之前,容器会调用Servlet的destroy()方法进行清理操作。
Servlet工作原理的核心是通过Web容器来管理和调度Servlet的生命周期。
Web容器负责接收请求、实例化Servlet、调用相关方法处理请求、生成响应并发送回客户端。
Servlet3.0实现文件上传的方法
![Servlet3.0实现文件上传的方法](https://img.taocdn.com/s3/m/94c488d45ebfc77da26925c52cc58bd63186936f.png)
Servlet3.0实现⽂件上传的⽅法Servlet 实现⽂件上传所谓⽂件上传就是将本地的⽂件发送到服务器中保存。
例如我们向百度⽹盘中上传本地的资源或者我们将写好的博客上传到服务器等等就是典型的⽂件上传。
Servlet 3.0上次完成⽂件下载功能使⽤的是 Servlet 2.5,但是想要完成⽂件上传,那么继续使⽤Servlet 2.5 肯定不是⼀个好的选择,因此我们使⽤ Servlet 3.0 来完成⽂件上传。
下⾯我来简单介绍⼀下 Servlet 3.0 的新特性:1、新增的注解⽀持该版本新增了若⼲注解,⽤于简化 Servlet、过滤器(Filter)和监听器(Listener)的声明,这使得 web.xml 部署描述⽂件从该版本开始不再是必选的了。
2、HttpServletRequest 对⽂件上传的⽀持此前,对于处理上传⽂件的操作⼀直是让开发者头疼的问题,因为 Servlet 本⾝没有对此提供直接的⽀持,需要使⽤第三⽅框架来实现,⽽且使⽤起来也不够简单。
如今这都成为了历史,Servlet 3.0 已经提供了这个功能,⽽且使⽤也⾮常简单。
Servlet 3.0 的新特性当然肯定不⽌这些,但是其他的新特性在这⾥我们暂时还⽤不到,也就不做过多了解了。
必要条件想要完成⽂件上传,肯定不是这么简单,它对浏览器端和服务器端都有许多的要求。
对浏览器的要求:1. ⼀个⽂件的⼤⼩⼀般肯定不⽌ 1 KB,既然这样,那么要上传⼀个⽂件肯定不能使⽤get⽅式了,所以上传⽂件时必须采⽤post ⽅式。
2. 2.表单中必须有⼀个⽂件上传项<input type="file"> ,⽽且必须有 name 属性。
3. 必须设置表单的enctype 属性值为multipart/form-data。
对服务器的要求:1. 当然,我们肯定得使⽤ Servlet 3.0。
2. Servlet3.0 中接收普通上传组件(除了⽂件上传组件)通过 request.getParameter(String)接收,⽽⽂件上传组件通过request.getPart(String)接收。
servlet实现文件上传与下载功能
![servlet实现文件上传与下载功能](https://img.taocdn.com/s3/m/251c9be4bb0d4a7302768e9951e79b8969026856.png)
servlet实现⽂件上传与下载功能本⽂实例为⼤家分享了servlet实现⽂件上传与下载的具体代码,供⼤家参考,具体内容如下内容我们分两⼤模块来进⾏讲解,即上传的实现,与下载的实现上传的实现注意了我们在写上传表单的时候必须声明提交⽅式为post类型,enctype="multipart/form-data",这样的话才能实现上传。
当我们提交表单的时候看看响应体中都有什么内容:好了,我们有了数据了,接下来我们怎么提取数据呢,注意我们已经不能使⽤requeest.getParamter()⽅法来进⾏参数的提取了,那怎么办呢,我们总不能⾃⼰写实现类来进⾏分割吧!我们可以使⽤Commons提供的⼩⼯具。
好了,让我们来看看具体的操作步骤吧!这⾥我就不详细说了,⼀⽂代码流过:/*** 需要解决的问题:* 1 必须要把⽂件存放到WEB-INF⽬录下,避免⽤户看到* 2 ⽂件名相关问题* 1 有的浏览器会传递绝对路径到name中,我们只需要进⾏拆分即可* 2⽂件重名问题,我们可以使⽤uuid* 3⽂件名乱码问题,我们已经解决了。
即request.setCharacterEncoding("utf-8");* 3 ⽂件打散问题* 1通过⾸字符打散* 2通过时间打散* 3通过hash打散* 4上传⽂件⼤⼩限制* 1单个⽂件上传⼤⼩限制* 2总⽂件上传⼤⼩限制* 设置这两个参数时,我们必须在没有解析之前执⾏。
* 5 缓存⼤⼩与临时⽬录*****/public class FileUploadServlet extends HttpServlet {public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");/*** 我们使⽤commmons的⼩⼯具来进⾏编码* 设置jsp页⾯的enctype= “multipart/form-data“;* 1 创建FileItem⼯⼚* 2创建ServletFileUpload对象* 3 解析request得到FileItem* 4对FileItem进⾏操作**/String path = request.getSession().getServletContext().getRealPath("/WEB-INF");//解决缓存⼤⼩,要不然你的内存会爆的。
Spring中MultipartHttpServletRequest实现文件上传
![Spring中MultipartHttpServletRequest实现文件上传](https://img.taocdn.com/s3/m/5d7103dddb38376baf1ffc4ffe4733687e21fc72.png)
Spring中MultipartHttpServletRequest实现⽂件上传xml 代码1. <bean id="multipartResolver"2. class="monsMultipartResolver">3. <!-- 设置上传⽂件的最⼤尺⼨为1MB -->4. <property name="maxUploadSize">5. <value>1048576</value>6. </property>7. </bean>这样⼀旦某个Request是⼀个MultipartRequest,它就会⾸先被MultipartResolver处理,然后再转发相应的Controller。
在UploadImageController中,将HttpServletRequest转型为MultipartHttpServletRequest,就能⾮常⽅便地得到⽂件名和⽂件内容:java 代码1. public ModelAndView handleRequest(HttpServletRequest request,2. HttpServletResponse response) throws Exception {3. // 转型为MultipartHttpRequest:4. MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;5. // 获得⽂件:6. MultipartFile file = multipartRequest.getFile(" file ");7. // 获得⽂件名:8. String filename = file.getOriginalFilename();9. // 获得输⼊流:10. InputStream input = file.getInputStream();11. // 写⼊⽂件12.13. // 或者:14. File source = new File(localfileName.toString());15. multipartFile.transferTo(source);16. }⽣成缩略图 (⽬录) 当⽤户上传了图⽚后,必须⽣成缩略图以便⽤户能快速浏览。
基于servlet的文件上传
![基于servlet的文件上传](https://img.taocdn.com/s3/m/ab1e3e816529647d27285224.png)
public class ServletFileOpt extends HttpServlet{/*** 使用Apache Commons fileupload组件,进行文件的上传** form 表单的 enctype属性改为 multipart/form-data*** 进度显示:* 1,利用监听器,获得上传的数据,并将其存入httpSession* 2,利用AJAX 不断的向服务器获得实时的文件上传数据*****/private String defalutExt = "rar,zip";//设置默认的文件上传格式private String allowExtension;//允许上传的文件格式private String errMsg;//错误消息提示private String contentType = "application/x-msdownload";//提供给浏览器文件的文本格式,"application/x-msdownload"表示所有private String encode = "UTF-8";//编码格式public static final int FILE_SIZE_MAX = 100*1024*1024 ;public static final int SIZE_MAX = 1024*1024*1024;public static final int SIZE_THRESHOLD = 100*1024;/****/private static final long serialVersionUID= 5830779787621377353L;protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {this.doPost(request, response);}protected void doPost(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {String method = (String)request.getParameter("method");if(!"".equals(method) || method != null){if("upload".equals(method)){this.upload(request, response);}else if("download".equals(method)){this.download(request, response);}else if("forward".equals(method)){this.forard(request, response);}}}/*** 文件上传* @param request* @param response* @throws ServletException* @throws IOException*/protected void upload(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// step 1 :创建一个硬盘文件项目工厂DiskFileItemFactory difc = new DiskFileItemFactory();// step 2 :设置文件大小的阈值,超过此值将使用临时文件保存收到的数据difc.setSizeThreshold(SIZE_THRESHOLD);// step 3 :设置临时文件的存放目录,要求使用绝对路径File temp = new File("D:" + File.separator + "temp");if(!temp.exists()){temp.mkdirs();}difc.setRepository(temp);// step 4 : 创建一个文件上传处理器ServletFileUpload sfu = new ServletFileUpload(difc);// step 6:设置允许上传的单个文件的最大字节sfu.setFileSizeMax(FILE_SIZE_MAX);// step 5:设置允许上传的文件的最大字节,若为-1则代表无限制sfu.setSizeMax(SIZE_MAX);sfu.setHeaderEncoding("UTF-8");final HttpSession httpSession = request.getSession();/*设置文件上传的进度监听器*/sfu.setProgressListener(new ProgressListener() {public void update(long pBytesRead, long pContentLength, int pItems) {DecimalFormat df = new DecimalFormat("0.00");double percent = ((double)pBytesRead/pContentLength)*100;// Logger logger = Logger.getLogger(ServletFileOPt.class.getName());// try {// Thread.sleep(100);// } catch (InterruptedException e) {// e.printStackTrace();// }// ("上传进度:" + df.format(percent) + "%");httpSession.setAttribute("percent",df.format(percent));}});if(!ServletFileUpload.isMultipartContent(request)){request.setAttribute("errMsg", "不是上传文件表单:");request.getRequestDispatcher("/fileUpload.jsp").forward(reques t, response);return ;}//创建文件存放的磁盘目录String path = this.getServletContext().getRealPath("WEB-INF/upload").replaceAll ("\\\\","/");File dir = new File(path);if(!dir.exists()){dir.mkdirs();}List<?> items = null;InputStream inStream = null;FileOutputStream fos = null;try {//step 7:解析请求,得到FileItem对象列表items = sfu.parseRequest(request);for(Iterator<?> iter = items.iterator(); iter.hasNext();){ //获得FileItem对象FileItem fileItem = (FileItem)iter.next();if(!fileItem.isFormField()){//设置允许上传的文件setAllowExtension("jpg,jpeg,bmp,png,swf,doc,xml,xls,ppt,jar,av i,wmv");//获得文件名,并重命名,防止文件名重复String fileName = fileItem.getName();fileName = String.valueOf(System.currentTimeMillis()) + "."+ fileName.substring(stIndexOf(".")+1);if(!isValid(fileName)){request.setAttribute("errMsg", "上传的文件不合法," +errMsg);request.getRequestDispatcher("/error.jsp").forward(request, response);return ;}/** 方法一:利用apache 文件上传组件提供的文件write()方法将文件输出到磁盘文件* fileItem.write(new File(dir,fileName));** 方法二:利用FileOutputStream将文件输出*///获得文件的字节写入流inStream = fileItem.getInputStream();//创建将上传文件写入到物理磁盘的文件输出流对象fos = new FileOutputStream(new File(dir,fileName));byte[] buffer = new byte[2048];int readBytes = 0;//文件的字节数据读取while((readBytes = inStream.read(buffer,0,2048)) != -1){fos.write(buffer,0,readBytes);}//关闭流通道inStream.close();fos.flush();fos.close();//删除临时文件,需要在流通道关闭后fileItem.delete();}}request.getRequestDispatcher("/success.jsp").forward(request, response);} catch (FileUploadException e) {e.printStackTrace();request.setAttribute("errMsg","文件上传失败!");request.getRequestDispatcher("/error.jsp").forward(request, response);}}/*** 文件下载。
servlet实现文件上传和文件下载
![servlet实现文件上传和文件下载](https://img.taocdn.com/s3/m/788bab2b4b73f242336c5ffc.png)
=
request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path
+"/" ;
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>
boolean isOk=download(request, response);// 具体实现 if(isOk==true){
request.getRequestDispatcher("success.jsp").forward(request, response); }else{
request.getRequestDispatcher("error.jsp").forward(request, response); } }
</servlet-mapping>
<servlet-mapping> <servlet-name>fileLoad</servlet-name> <url-pattern>/fileLoad</url-pattern>
</servlet-mapping>
</web-app>
index.jsp 如下
public boolean download(HttpServletRequest request,HttpServletResponse response) {
servlet工作原理
![servlet工作原理](https://img.taocdn.com/s3/m/e5434016bc64783e0912a21614791711cd797971.png)
servlet工作原理Servlet是一种Java技术,用于构建基于服务器的Web应用程序。
它的主要工作原理包括以下几个方面:1. Servlet的生命周期:Servlet有三个主要阶段的生命周期,分别是初始化、服务和销毁。
在初始化阶段,Servlet会被加载并初始化一些资源。
在服务阶段,Servlet会根据请求生成相应的输出,并将其发送给客户端。
在销毁阶段,Servlet被卸载并释放相关资源。
2. 客户端请求:当客户端发送一个HTTP请求到服务器时,请求会被服务器接收并解析。
服务器会通过解析请求中的URL找到对应的Servlet 类,并创建一个Servlet实例。
3. 实例化Servlet:服务器根据Servlet类的定义,使用Java反射机制创建Servlet的一个实例。
每个实例都是单线程,因此可以在同一时间处理多个请求。
4. 初始化:在实例化后,服务器会调用Servlet的init(方法来初始化Servlet。
在这个方法中,Servlet可以执行一些初始化操作,如加载配置文件、连接数据库等。
5. 请求处理:当Servlet初始化完成后,服务器会调用Servlet的service(方法来处理客户端请求。
在这个方法中,Servlet可以通过HttpServletRequest对象获取客户端的请求信息,并通过HttpServletResponse对象生成对应的响应。
6. 响应返回:在service(方法中,Servlet将生成的响应信息写入到HttpServletResponse对象中。
服务器将根据响应信息生成一个HTTP 响应并将其发送给客户端。
7. 销毁:当服务器关闭或Web应用程序重新部署时,Servlet将被销毁。
在销毁之前,服务器会调用Servlet的destroy(方法来释放资源和执行一些清理操作。
8. 多线程处理:由于Servlet是单实例多线程的,服务器会为每个请求创建一个新的线程。
servlet程序的运行原理
![servlet程序的运行原理](https://img.taocdn.com/s3/m/f0da1a849a89680203d8ce2f0066f5335a8167f7.png)
servlet程序的运行原理宝子们!今天咱们来唠唠Servlet程序的运行原理,这可超级有趣呢!Servlet是啥呢?你可以把它想象成一个超级小助手,住在服务器这个大屋子里。
这个小助手的任务就是接收来自客户端的各种请求,就像接收客人的订单一样。
比如说,你在浏览器里输入一个网址,这就是一个请求啦,这个请求就像一个小纸条,写着你想要的东西。
当这个请求从客户端出发,就踏上了寻找Servlet小助手的旅程。
它得先通过网络这个大通道,这个通道有时候快,有时候慢,就像咱们平时走的路,有时候堵车,有时候畅通无阻。
一旦这个请求到达了服务器所在的地方,服务器就开始找合适的Servlet来处理这个请求。
这就好比在一个大公司里,前台收到了客人的需求,然后得找到负责这个事情的部门或者员工。
那服务器怎么知道哪个Servlet能处理这个请求呢?这里面有个小秘密哦。
每个Servlet都有自己擅长处理的请求类型或者特定的路径。
就像每个员工都有自己负责的业务范围一样。
比如说,有个Servlet专门处理用户登录的请求,那如果是登录相关的请求,服务器就会把这个请求交给这个专门的Servlet小助手。
当找到合适的Servlet之后呢,这个Servlet就开始干活啦。
它会根据请求的内容,在服务器上进行各种操作。
可能是从数据库里找数据,就像在仓库里找东西一样。
数据库里存着好多好多有用的信息,像用户的账号密码啊,商品的信息之类的。
Servlet会根据请求的要求,从这个大仓库里把需要的东西找出来。
然后呢,Servlet小助手可不会把从数据库里找来的原始数据就这么直接扔回去给客户端哦。
它得把这些数据整理成客户端能看得懂的形式。
这就好比把仓库里找到的原材料加工成美味的食物一样。
它会把数据包装成HTML之类的格式,这样浏览器就能愉快地显示给用户看啦。
最后呢,这个包装好的回复就像一个装满礼物的包裹,沿着网络通道再送回给客户端。
客户端收到这个回复后,就会把里面的内容显示出来,比如显示一个登录成功的页面,或者是显示你想要查询的商品信息。
Web应用中的文件上传及其实现
![Web应用中的文件上传及其实现](https://img.taocdn.com/s3/m/85b751002f3f5727a5e9856a561252d380eb209c.png)
Web应用中的文件上传及其实现文件上传是Web应用中常见的功能之一,在用户上传图片、文档、视频或其他文件的过程中,需要实现简单且高效的文件上传功能。
本文将从文件上传的基本原理入手,介绍文件上传的实现过程,以及文件上传过程中需要考虑的安全性、性能和用户体验等方面。
一、文件上传的基本原理在Web应用中,文件上传的基本原理是通过浏览器将文件传输到Web服务器上。
用户通过填写表单或者拖放文件的形式选择要上传的文件,然后点击上传按钮,浏览器会将文件发送到服务器端,服务器端接收到文件后进行处理。
在文件上传的过程中,可能需要对文件进行验证、存储、处理等操作。
下面将介绍文件上传的具体实现过程。
二、文件上传的实现过程1. HTML表单文件上传最常见的文件上传方式是通过HTML表单实现,用户通过<input type="file">标签在表单中选择要上传的文件,然后用户提交表单,浏览器会将文件上传到服务器端。
需要注意的是,表单的enctype属性必须设置为"multipart/form-data",同时还需要确保表单的method 属性为"post"。
示例代码如下:```<form action="/upload" method="post"enctype="multipart/form-data"><input type="file" name="file"><input type="submit" value="Upload"></form>```2. Ajax文件上传除了通过表单提交文件外,还可以使用Ajax技术实现文件上传。
通过JavaScript代码监听文件选择事件,将文件通过Ajax方式发送到服务器端。
serverlet的工作原理
![serverlet的工作原理](https://img.taocdn.com/s3/m/1fc39084a0c7aa00b52acfc789eb172dec639959.png)
serverlet的工作原理Servlet是Java Web开发中的一个重要组件,它是运行在Web服务器上的Java程序,用于处理客户端(浏览器)发送的请求并返回响应。
Servlet的工作原理如下:1. 客户端发送请求:当用户在浏览器中访问某个URL时,浏览器会向Web服务器发送一个HTTP请求。
2. Servlet容器接收请求:Web服务器中的Servlet容器(例如Tomcat)接收到请求,并根据请求的URL将其分派给相应的Servlet进行处理。
3. 加载Servlet:Servlet容器根据请求的URL查找并加载相应的Servlet类。
每个Servlet类都需要继承自javax.servlet.http.HttpServlet,并通过注解或配置文件与URL进行映射。
4. 初始化Servlet:Servlet容器在加载Servlet类后,会调用其init()方法进行初始化操作。
在这个方法中,Servlet可以进行一些初始化配置,例如读取配置文件、建立数据库连接等。
5. 处理请求:一旦Servlet被初始化后,Servlet容器会创建一个新的线程来处理该请求。
Servlet类中的service()方法负责处理请求,并根据请求的类型(GET、POST等)调用对应的doGet()、doPost()等方法来具体处理请求,例如获取请求参数、验证用户身份等。
6. 生成响应:Servlet处理请求后,可以生成相应的数据,并将其封装成一个HTTP响应,包括响应头和响应体。
可以通过设置响应头来控制缓存、重定向、设置Cookie等。
7. 返回响应:Servlet容器将生成的响应返回给客户端,这个响应经过Web服务器会由浏览器进行解析和展示。
8. 销毁Servlet:当Web服务器关闭或者应用程序被卸载时,Servlet容器会调用Servlet的destroy()方法进行销毁操作。
在这个方法中,可以进行一些资源释放的操作,例如关闭数据库连接、释放内存等。
聊聊在Servlet中怎么上传文件
![聊聊在Servlet中怎么上传文件](https://img.taocdn.com/s3/m/5673cd6b178884868762caaedd3383c4bb4cb42c.png)
聊聊在Servlet中怎么上传⽂件⾸先对Servlet上传⽂件的简单理解此前,Servlet本⾝没有对⽂件上传提供直接的⽀持,⼀般需要使⽤第三⽅框架来实现,这样就⽐较⿇烦不过,Servlet3.0之后提供了这个功能,⽽且使⽤⾮常简单,,为此,HTTPServletRequest提供了两个⽅法⽤于从请求中解析出上传的⽂件:Part getPart(String name) //获取请求中给定 name 的⽂件Collection<Part> getParts() //获取所有的⽂件其中每⼀个⽂件⽤⼀个javax.servlet.http.Part对象来表⽰,该接⼝提供了处理⽂件的简易⽅法,如write(),delete(),那么,结合 HttpServletRequest 和 Part 来保存上传的⽂件变得⾮常简单Part img = request.getPart("img");img.write("根路径+\\img.jpg")注意:可以配合 @MultipartConfig 注解来对上传操作进⾏⼀些⾃定义的配置,⽐如限制上传⽂件的⼤⼩,以及保存⽂件的路径等,但是,如果请求的 MIME 类型不是 multipart/form-data,则不能使⽤上⾯的两个⽅法,否则将抛异常。
⾸先我们掌握开发Servlet的步骤:前端:如果有前端内容的话,需要再写⼀个html⽂件后端⾸先编写后台的Servlet代码(也即重写doGet和doPost⽅法)配置项⽬⽂件,web.xml⾥⾯的映射⽂件1.⾸先写⼀个页⾯(前端) html ⽂件<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>上传⽂件</title></head><body><form action="upload" method="post" enctype="multipart/form-data"><input type="file" name="img"><p><input type="submit" value=" 提交 "></form></body></html>代码分析2.写Servlet后端类代码import javax.servlet.ServletException;import javax.servlet.annotation.MultipartConfig;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.Part;import java.io.IOException;import java.io.PrintWriter;//⾸先必须声明这个类是⽤来处理(⽂件)流的【不可获取】@MultipartConfigpublic class FileServlet extends HttpServlet {@Override//因为提交表单只需要post,那么这⾥就不需要get⽅法了protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//⾸先拿到流信息,他返回的是⼀个part对象Part part = req.getPart("img");//⼿下声明⼀个保存路径,这⾥保存在D盘的File⽂件下String filePath = "D:\\File\\";//保存⽂件的名称这⾥就和原⽂件的名称⼀样,通过part⾥⾯的⽅法得到原⽂件名称String fileName = part.getSubmittedFileName();//通过write⽅法,可以将这个png⽂件保存在任意路径下,write⾥⾯的参数,就是要保存的路径part.write(filePath+fileName);//然后给前端返回响应的结果resp.setContentType("text/html");resp.setCharacterEncoding("utf-8");PrintWriter writer = resp.getWriter();writer.println("<h1>上传成功</h1>");}}3.配置web.xml映射<servlet><servlet-name>fileServlet</servlet-name> <servlet-class>FileServlet</servlet-class> </servlet><servlet-mapping><servlet-name>fileServlet</servlet-name> <url-pattern>/upload</url-pattern></servlet-mapping>4.效果展⽰存在问题那么哪⾥存在问题呢?//⾸先拿到流信息,他返回的是⼀个part对象Part part = req.getPart("img");//⼿下声明⼀个保存路径,这⾥保存在D盘的File⽂件下String filePath = "D:\\File\\";//保存⽂件的名称这⾥就和原⽂件的名称⼀样,通过part⾥⾯的⽅法得到原⽂件名称String fileName = part.getSubmittedFileName();//通过write⽅法,可以将这个png⽂件保存在任意路径下,write⾥⾯的参数,就是要保存的路径part.write(filePath+fileName);注意:其实这⾥是存在⼀点问题的那么如何进⾏改进呢?⽅法:使⽤UUID作为⽂件名代码改进:也就是把代码中的fileName改成如下//⾸先需要⼀个⽂件名,改进⽂件名的名称(防⽌重复名称覆盖之前的⽂件)String fileName = UUID.randomUUID().toString()+part.getSubmittedFileName().substring(part.getSubmittedFileName().indexOf("."));结果验证:以上就是聊聊在Servlet中怎么上传⽂件的详细内容,更多关于Java Servlet上传⽂件的资料请关注其它相关⽂章!。
Servlet实现文件上传的三种方法总结
![Servlet实现文件上传的三种方法总结](https://img.taocdn.com/s3/m/42ae4b5ace84b9d528ea81c758f5f61fb7362899.png)
Servlet实现⽂件上传的三种⽅法总结Servlet实现⽂件上传的三种⽅法总结1. 通过getInputStream()取得上传⽂件。
/*** To change this template, choose Tools | Templates* and open the template in the editor.*/package net.individuals.web.servlet;import java.io.DataInputStream;import java.io.FileOutputStream;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/**** @author Barudisshu*/@WebServlet(name = "UploadServlet", urlPatterns = {"/UploadServlet"})public class UploadServlet extends HttpServlet {/*** Processes requests for both HTTP* <code>GET</code> and* <code>POST</code> methods.** @param request servlet request* @param response servlet response* @throws ServletException if a servlet-specific error occurs* @throws IOException if an I/O error occurs*/protected void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");//读取请求Bodybyte[] body = readBody(request);//取得所有Body内容的字符串表⽰String textBody = new String(body, "ISO-8859-1");//取得上传的⽂件名称String fileName = getFileName(textBody);//取得⽂件开始与结束位置Position p = getFilePosition(request, textBody);//输出⾄⽂件writeTo(fileName, body, p);}//构造类class Position {int begin;int end;public Position(int begin, int end) {this.begin = begin;this.end = end;}}private byte[] readBody(HttpServletRequest request) throws IOException {//获取请求⽂本字节长度int formDataLength = request.getContentLength();//取得ServletInputStream输⼊流对象DataInputStream dataStream = new DataInputStream(request.getInputStream());byte body[] = new byte[formDataLength];int totalBytes = 0;while (totalBytes < formDataLength) {int bytes = dataStream.read(body, totalBytes, formDataLength);totalBytes += bytes;}return body;}private Position getFilePosition(HttpServletRequest request, String textBody) throws IOException {//取得⽂件区段边界信息String contentType = request.getContentType();String boundaryText = contentType.substring(stIndexOf("=") + 1, contentType.length());//取得实际上传⽂件的⽓势与结束位置int pos = textBody.indexOf("filename=\"");pos = textBody.indexOf("\n", pos) + 1;pos = textBody.indexOf("\n", pos) + 1;pos = textBody.indexOf("\n", pos) + 1;int boundaryLoc = textBody.indexOf(boundaryText, pos) - 4;int begin = ((textBody.substring(0, pos)).getBytes("ISO-8859-1")).length;int end = ((textBody.substring(0, boundaryLoc)).getBytes("ISO-8859-1")).length;return new Position(begin, end);}private String getFileName(String requestBody) {String fileName = requestBody.substring(requestBody.indexOf("filename=\"") + 10);fileName = fileName.substring(0, fileName.indexOf("\n"));fileName = fileName.substring(fileName.indexOf("\n") + 1, fileName.indexOf("\""));return fileName;}private void writeTo(String fileName, byte[] body, Position p) throws IOException {FileOutputStream fileOutputStream = new FileOutputStream("e:/workspace/" + fileName);fileOutputStream.write(body, p.begin, (p.end - p.begin));fileOutputStream.flush();fileOutputStream.close();}// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."> /*** Handles the HTTP* <code>GET</code> method.** @param request servlet request* @param response servlet response* @throws ServletException if a servlet-specific error occurs* @throws IOException if an I/O error occurs*/@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}/*** Handles the HTTP* <code>POST</code> method.** @param request servlet request* @param response servlet response* @throws ServletException if a servlet-specific error occurs* @throws IOException if an I/O error occurs*/@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}/*** Returns a short description of the servlet.** @return a String containing servlet description*/@Overridepublic String getServletInfo() {return "Short description";}// </editor-fold>}2. 通过getPart()、getParts()取得上传⽂件。
web servlet工作原理
![web servlet工作原理](https://img.taocdn.com/s3/m/e58844b185868762caaedd3383c4bb4cf6ecb77a.png)
web servlet工作原理Web Servlet是一种用于开发Web应用程序的Java技术。
它是基于服务器端的Java组件,用于处理客户端的HTTP请求并生成响应。
本文将介绍Web Servlet的工作原理,从请求处理到响应生成的整个过程。
Web Servlet工作的基本原理是通过Servlet容器来实现的。
Servlet容器是Web服务器或应用服务器中的一部分,负责管理和执行Servlet的生命周期。
当客户端发送一个HTTP请求到服务器时,Servlet容器会根据请求的URL找到对应的Servlet,并将请求转发给它。
Servlet容器首先会创建一个ServletRequest对象和一个ServletResponse对象。
ServletRequest对象封装了客户端的请求信息,包括请求的方法、URL、参数、头部等。
ServletResponse 对象用于生成响应,包括设置响应的状态码、头部、内容等。
接下来,Servlet容器将ServletRequest和ServletResponse对象作为参数,调用Servlet的service()方法。
在service()方法中,开发人员可以编写自己的业务逻辑来处理请求和生成响应。
Servlet可以读取ServletRequest对象中的请求参数,执行相应的操作,然后将结果写入ServletResponse对象中。
在service()方法执行完成后,Servlet容器将ServletResponse对象中的内容发送回客户端,完成整个请求-响应过程。
客户端收到响应后,根据响应的内容进行相应的处理。
除了service()方法,Servlet还可以重写其他方法来处理特定的HTTP请求。
例如,doGet()方法用于处理GET请求,doPost()方法用于处理POST请求。
通过重写这些方法,开发人员可以更加灵活地处理不同类型的请求。
在Servlet的生命周期中,还有一些其他的方法可以被重写。
java-servlet实现带进度条的上传下载功能
![java-servlet实现带进度条的上传下载功能](https://img.taocdn.com/s3/m/70285b0fa6c30c2259019e41.png)
Servlet实现上传下载并显示进度条。
总有人找上传下载的例子,一搜也能搜出来好多结果,但是应用起来可能不那么简单。
本文使用servelet最原始的方法,实现简单的上传下载功能,并且显示上传进度条。
首先贴上来一个标准的web_proj的结构目录:
需要引入lib下面的两个包,只需要这两个包,这个在文档的最后我会把相关的源码插入到word中,为了避免拿来主义,这里不分享项目源文件,但是我会贴出来源码。
这里先说明一下原理,先说下载,其实就是简单的一个url的方式,这个不多说,然后说上传。
其实就是页面选择文件,点击上传后通过servlet操作文件流,然后把文件留写入本地。
但是进度条是怎么实现的呢,就是前台一个不断循环的ajax方法每隔很短的时间就请求后台,在文件上传的时候我们能拿到这个文件的size,而ajax请求或者已经写入的文件的size,这样我就能算出来,上传了百分之多少,每秒上传多少等。
先看效果图:
贴一段xml的代码
其中主要工作的环节,这里通过配置url-pattern,拦截ajax请求以及表单提交。
转入对应的servelet进行对应的处理。
filetest.zip
左侧是插入了源码文件对象,需要的自行下载。
Servlet工作原理
![Servlet工作原理](https://img.taocdn.com/s3/m/a83e5ee30129bd64783e0912a216147916117e7c.png)
Servlet工作原理Servlet是Java编写的服务器端程序,它能够处理来自客户端的HTTP请求并生成相应的HTTP响应。
了解Servlet的工作原理对于开发和理解Web应用程序非常重要。
Servlet工作原理的核心是Servlet容器。
Servlet容器负责管理和执行Servlet的生命周期,并将请求传递给适当的Servlet进行处理。
下面是Servlet工作原理的详细解释:1. 客户端发送HTTP请求到服务器。
2. 服务器接收到请求后,将请求传递给Servlet容器。
3. Servlet容器根据请求的URL路径找到对应的Servlet。
4. Servlet容器创建一个Servlet实例(如果没有已经存在的实例)。
5. Servlet容器调用Servlet的init()方法进行初始化。
在这个方法中,Servlet可以进行一些必要的初始化工作,例如加载配置文件、建立数据库连接等。
6. Servlet容器调用Servlet的service()方法。
这个方法接收请求并生成响应。
在这个方法中,Servlet可以通过request对象获取请求的参数、头信息等,并通过response对象生成响应的内容。
7. Servlet容器将响应发送回客户端。
8. 如果Servlet容器检测到Servlet实例不再需要,它会调用Servlet的destroy()方法进行销毁。
在这个方法中,Servlet可以进行一些清理工作,例如关闭数据库连接、释放资源等。
Servlet工作原理的关键在于Servlet容器的管理和调用。
Servlet容器负责将请求传递给正确的Servlet实例,并在需要时创建和销毁实例。
这种机制使得Servlet 能够高效地处理并发请求,并且可以动态地加载和卸载Servlet。
除了处理HTTP请求和生成HTTP响应外,Servlet还可以与其他Java类和技术进行交互,例如数据库访问、文件操作等。
Servlet可以通过Java的标准API或第三方库来实现这些功能。
servlet工作原理
![servlet工作原理](https://img.taocdn.com/s3/m/4b8a21f568dc5022aaea998fcc22bcd126ff42e4.png)
servlet工作原理Servlet工作原理。
Servlet是Java编写的服务器端程序,它可以接收客户端的请求并作出相应的处理。
那么,Servlet是如何工作的呢?接下来我们就来详细介绍一下Servlet的工作原理。
首先,当客户端发送请求时,请求会首先到达服务器。
服务器会根据请求的URL来判断是哪个Servlet需要处理这个请求。
然后,服务器会创建一个线程来处理这个请求,这个线程会负责整个请求-响应的过程。
接着,服务器会调用Servlet的init()方法来初始化这个Servlet。
init()方法只在Servlet被创建时调用一次,它用来进行一些初始化的工作,比如读取配置文件、连接数据库等操作。
然后,服务器会调用Servlet的service()方法来处理客户端的请求。
service()方法会根据请求的类型(GET、POST等)来调用相应的doGet()、doPost()等方法来处理具体的业务逻辑。
在这个过程中,Servlet可以通过request对象来获取客户端的请求信息,并通过response对象来向客户端发送响应。
在处理完客户端的请求后,服务器会调用Servlet的destroy()方法来销毁这个Servlet。
destroy()方法只在Servlet被销毁时调用一次,它用来进行一些清理的工作,比如关闭数据库连接、释放资源等操作。
总的来说,Servlet的工作原理可以概括为,接收请求、初始化、处理请求、发送响应、销毁。
通过这个过程,Servlet可以实现与客户端的交互,完成各种不同的业务逻辑。
需要注意的是,由于Servlet是基于Java编写的,因此它具有跨平台性和高可移植性。
这也是Servlet在Web开发中得到广泛应用的重要原因之一。
总结一下,通过本文的介绍,我们对Servlet的工作原理有了更深入的了解。
希望本文能够帮助大家更好地理解Servlet,并在实际开发中发挥更大的作用。
Servlet工作原理
![Servlet工作原理](https://img.taocdn.com/s3/m/34948949773231126edb6f1aff00bed5b9f373ca.png)
Servlet工作原理Servlet是Java编写的服务器端程序,用于处理客户端的请求并生成响应。
它是Java Servlet API的一部份,通过在Java虚拟机中运行,可以实现动态网页的生成和处理。
本文将详细介绍Servlet的工作原理。
一、Servlet容器Servlet容器是一个运行Servlet的环境,负责接收客户端请求、调用相应的Servlet进行处理,并将生成的响应返回给客户端。
常见的Servlet容器有Tomcat、Jetty等。
二、Servlet生命周期Servlet的生命周期包括初始化、服务和销毁三个阶段。
1. 初始化阶段在Servlet容器启动时,会根据web.xml配置文件或者注解来加载和初始化Servlet。
容器会创建一个Servlet实例,并调用其init()方法进行初始化操作。
在init()方法中,可以进行一些必要的资源加载和初始化设置。
2. 服务阶段一旦Servlet初始化完成,它就可以接收客户端的请求并生成响应。
每一个请求都会创建一个新的线程,Servlet容器会调用Servlet的service()方法来处理请求。
在service()方法中,可以通过HttpServletRequest对象获取请求参数、请求头等信息,并通过HttpServletResponse对象生成响应内容。
3. 销毁阶段当Servlet容器关闭时,或者在web应用程序重新加载或者卸载时,会调用Servlet的destroy()方法进行资源释放和清理操作。
在destroy()方法中,可以释放打开的数据库连接、关闭文件流等。
三、Servlet请求处理过程当客户端发送一个HTTP请求到Servlet容器时,Servlet容器会按照以下步骤进行请求处理:1. 客户端发送HTTP请求到Servlet容器。
2. Servlet容器接收到请求后,根据请求的URL路径找到对应的Servlet。
3. Servlet容器创建一个HttpServletRequest对象,封装请求的相关信息,如请求方法、请求头、请求参数等。
Servlet中文件上传的几种方式
![Servlet中文件上传的几种方式](https://img.taocdn.com/s3/m/a760eccb8ad63186bceb19e8b8f67c1cfad6eee5.png)
Servlet中⽂件上传的⼏种⽅式 上传⽂件,因为上传的都是⼆进制数据,所以在Servlet中就不能直接⽤request.getParameter();⽅法进⾏数据的获取,需要借助第三⽅jar包对上传的⼆进制⽂件进⾏解析。
常⽤的⽅式如下:⼀:使⽤SmartUpload.jar 它是⼀个商业类库,解析request过程中,数据是存放在内存中的,因此速度⽐较快,但是上传⼤⽂件的时候会出现内存溢出。
⼆:commons-fileupload.jar (Apache commons)、commons-io.jarUploadFileServlet .javapublic class UploadFileServlet extends HttpServlet {/****/private static final long serialVersionUID = 1L;@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().println("请以POST⽅式访问该URL");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置请求和响应的编码格式String encoding = getServletContext().getInitParameter("encoding");req.setCharacterEncoding(encoding);resp.setCharacterEncoding(encoding);resp.setContentType("text/html");//核⼼ApiFileItemFactory factory = new DiskFileItemFactory();ServletFileUpload fileUpload = new ServletFileUpload(factory);//判断是否是muitipart/form-data类型if(!ServletFileUpload.isMultipartContent(req)) {resp.getWriter().println("表单的enctype属性不是multipart/form-data类型");}//设置单个⽂件上传⼤⼩ 2MfileUpload.setFileSizeMax(2*1024*1024);//设置总上传⽂件⼤⼩(有时候⼀次性上传多个⽂件,需要有⼀个上限,此处为10M)fileUpload.setSizeMax(10*1024*1024);//设置上传监听器[参数为⾃定义的监听器]fileUpload.setProgressListener(new ListenerUploadProgress());//解析请求try {List<FileItem> parseRequest = fileUpload.parseRequest(req);//获取数据for (FileItem fileItem : parseRequest) {//判断数据类型是不是普通的form表单字段if(!fileItem.isFormField()) {//上传⽂件String fileName = fileItem.getName();InputStream fileStream = fileItem.getInputStream();//定义保存的⽗路径String parentDir = this.getServletContext().getRealPath("/WEB-INF/upload");//使⽤UUID+⽂件名的⽅式,避免⽂件重名String realFileName = UUID.randomUUID().toString()+"-"+fileName;//创建要保存的⽂件File file = new File(parentDir,realFileName);//判断⽂件夹是否存在if(!file.getParentFile().exists()) {//创建⽂件夹[多级⽂件夹]file.madir是创建单⼀⽂件夹file.getParentFile().mkdirs();}//创建输出流OutputStream out = new FileOutputStream(file);//创建字节缓存byte[] buffer = new byte[1024];int len = -1;//⼀次读取1kb(1024byte),返回-1表明读取完毕while((len = fileStream.read(buffer))!=-1) {//⼀次写⼊1kb(1024byte)out.write(buffer,0, len);}//冲刷流资源out.flush();//关闭流out.close();fileStream.close();}else {//普通字段//字段名String fieldName = fileItem.getFieldName();//字段值String fieldValue = fileItem.getString();System.out.println(fieldName+":"+fieldValue);}}} catch (FileUploadException e) {e.printStackTrace();}}}ListenerUploadProgress.javapublic class ListenerUploadProgress implements ProgressListener { /*** @param bytesRead 已经读取的字节数* @param contentLength ⽂件总长度* @param items 当前上传的是哪个⽂件*/@Overridepublic void update(long bytesRead, long contentLength, int items) { System.out.println(bytesRead);System.out.println(contentLength);System.out.println(items);}//*前端可以根据该信息写⼀个上传进度条}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用Servlet 进行文件上传的原理和实现Servlet 是用 Java 编写的、协议和平台都独立的服务器端组件,使用请求/响应的模式,提供了一个基于 Java 的服务器解决方案。
使用 Servlet 可以方便地处理在 HTML 页面表单中提交的数据,但 Servlet 的 API 没有提供对以 mutilpart/form-data 形式编码的表单进行解码的支持,因而对日常应用中经常涉及到到文件上传等事务无能为力。
如何用 Servlet 进行文件的上传,必须编程实现。
一、基本原理通过 HTML 上载文件的基本流程如下图所示。
浏览器端提供了供用户选择提交内容的界面(通常是一个表单),在用户提交请求后,将文件数据和其他表单信息编码并上传至服务器端,服务器端(通常是一个 cgi 程序)将上传的内容进行解码了,提取出 HTML 表单中的信息,将文件数据存入磁盘或数据库。
二、各过程详解A)填写表单并提交通过表单提交数据的方法有两种,一种是 GET 方法,另一种是 POST 方法,前者通常用于提交少量的数据,而在上传文件或大量数据时,应该选用 POST 方法。
在 HTML 代码中,在 <form> 标签中添加以下代码可以页面上显示一个选择文件的控件。
<input type="file" name="file01">在页面中显示如下(可能随浏览器不同而不同)可以直接在文本框中输入文件名,也可以点击按钮后弹出供用户选择文件的对话框。
B)浏览器编码在向服务器端提交请求时,浏览器需要将大量的数据一同提交给 Server 端,而提交前,浏览器需要按照 Server 端可以识别的方式进行编码,对于普通的表单数据,这种编码方式很简单,编码后的结果通常是 field1=value2&field2=value2&…的形式,如name=aaaa&Submit=Submit。
这种编码的具体规则可以在 rfc2231 里查到,通常使用的表单也是采用这种方式编码的,Servlet 的 API 提供了对这种编码方式解码的支持,只需要调用 ServletRequest 类中的方法就可以得到用户表单中的字段和数据。
这种编码方式( application/x-www-form-urlencoded )虽然简单,但对于传输大块的二进制数据显得力不从心,对于传输这类数据,浏览器采用了另一种编码方式,即 "multipart/form-data"的编码方式,采用这种方式,浏览器可以很容易的表单内的数据和文件一起。
这种编码方式先定义好一个不可能在数据中出现的字符串作为分界符,然后用它将各个数据段分开,而对于每个数据段都对应着 HTML 页面表单中的一个 Input 区,包括一个 content-disposition 属性,说明了这个数据段的一些信息,如果这个数据段的内容是一个文件,还会有Content-Type 属性,然后就是数据本身。
这里,我们可以编写一个简单的 Servlet 来看到浏览器到底是怎样编码的。
实现流程:∙重载 HttpServlet 中的 doPost 方法∙调用 request.getContentLength() 得到 Content-Length ,并定义一个与 Content-Length 大小相等的字节数组 buffer 。
∙从HttpServletRequest 的实例 request 中得到一个 InputStream, 并把它读入 buffer 中。
∙使用 FileOutputStream 将 buffer 写入指定文件。
代码清单// ReceiveServlet.javaimport java.io.*;import javax.servlet.*;import javax.servlet.http.*;//示例程序:记录下Form提交上来的数据,并存储到Log文件中public class ReceiveServlet extends HttpServlet{public void doPost(HttpServletRequest request,HttpServletResponse response)throws IOException, ServletException{//1int len = request.getContentLength();byte buffer[] = new byte[len];//2InputStream in = request.getInputStream();int total = 0;int once = 0;while ((total < len) && (once >=0)) {once = in.read(buffer,total,len);total += once;}//3OutputStream out=new BufferedOutputStream( new FileOutputStream("Receive.log",true)); byte[] breaker="\r\nNewLog: -------------------->\r\n".getBytes();System.out.println(request.getContentType());out.write(breaker,0,breaker.length);out.write(buffer);out.close();in.close();}}在使用 Opera 作为浏览器测试时,从指定的文件( Receive.log )中可以看到如下的内容--_OPERAB__-T/DQLi2fn47+D52OOrpdrzContent-Disposition: form-data; name="id"id00--_OPERAB__-T/DQLi2fn47+D52OOrpdrzContent-Disposition: form-data; name="file3"; filename="Autoexec.bat"Content-Type: application/octet-stream@echo offprompt $d $t [ $p ]$_$$--_OPERAB__-T/DQLi2fn47+D52OOrpdrz--这里 _OPERAB__-T/DQLi2fn47+D52OOrpdrz 就是浏览器指定的分界符,不同的浏览器有不同的确定分界符的方法,但都需要保证分界符不会在文件内容中出现。
下面是用 IE 进行测试的结果-----------------------------7d137a26e18Content-Disposition: form-data; name="name"123-----------------------------7d137a26e18Content-Disposition: form-data; name="introduce"I am...I am..-----------------------------7d137a26e18Content-Disposition: form-data; name="file3"; filename="C:\Autoexec.bat"Content-Type: application/octet-stream@echo offprompt $d $t [ $p ]$_$$SET PATH=d:\pf\IBMVJava2\eab\bin;%PATH%;D:\PF\ROSE98I\COMMON-----------------------------7d137a26e18--这里 ---------------------------7d137a26e18 作为分界符。
关于分界符的规则可以概况为两条:∙除了最后一个分界符,每个分界符后面都加一个 CRLF 即 '\u000D' 和 '\u000A', 最后一个分界符后面是两个分隔符"--"∙每个分界符的开头也要加一个 CRLF 和两个分隔符("-")。
浏览器采用默认的编码方式是 application/x-www-form-urlencoded ,可以通过指定 form 标签中的 enctype 属性使浏览器知道此表单是用 multipart/form-data 方式编码如:< form action="/servlet/ReceiveServlet" ENCTYPE="multipart/form-data" method=post >C)提交请求提交请求的过程由浏览器完成的,并且遵循 HTTP 协议,每一个从浏览器端到服务器端的一个请求,都包含了大量与该请求有关的信息,在 Servlet 中,HttpServletRequest 类将这些信息封装起来,便于我们提取使用。
在文件上载和表单提交的过程中,有两个关心的问题,一是上载的数据是是采用的那种方式的编码,这个问题的可以从Content-Type 中得到答案,另一个是问题是上载的数据量有多少即 Content-Length ,知道了它,就知道了 HttpServletRequest 的实例中有多少数据可以读取出来。
这两个属性,我们都可以直接从 HttpServletRequest 的一个实例中获得,具体调用的方法是 getContentType() 和getContentLength() 。
Content-Type 是一个字符串,在上面的例子中,增加System.out.println(request.getContentType());可以得到这样的一个输出字符串:multipart/form-data;boundary=---------------------------7d137a26e18前半段正是编码方式,而后半段正是分界符;任务分解上述的字符串,取出分界符。
通过 String 类中的方法,我们可以把这个字符串分解,提取出分界符。
String contentType = request.getContentType( );int start = contentType.indexOf("boundary=");int boundaryLen = new String("boundary=").length();String boundary = contentType.substring(start+boundaryLen);boundary = "--" + boundary;判断编码方式可以直接用 String 类中的 startsWith 方法判断。