用 Servlet 进行文件上传的原理和实现

合集下载

用JSP_Servlet实现文件上传

用JSP_Servlet实现文件上传

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工作原理

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实现文件上传的方法

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实现文件上传与下载功能

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实现文件上传

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的文件上传

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实现文件上传和文件下载

=
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工作原理

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是单实例多线程的,服务器会为每个请求创建一个新的线程。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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 方法判断。

相关文档
最新文档