ImageVerifierCode 换一换
格式:DOC , 页数:16 ,大小:95KB ,
资源ID:11234757      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/11234757.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(用-Servlet-进行文件上传的原理和实现.doc)为本站上传会员【仙人****88】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

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

1、用 Servlet 进行文件上传的原理和实现 Servlet 是用 Java 编写的、协议和平台都独立的服务器端组件,使用请求/响应的模式,提供了一个基于 Java 的服务器解决方案。使用 Servlet 可以方便地处理在 HTML 页面表单中提交的数据,但 Servlet 的 API 没有提供对以 mutilpart/form-data 形式编码的表单进行解码的支持,因而对日常应用中经常涉及到到文件上传等事务无能为力。 如何用 Servlet 进行文件的上传,必须编程实现。 一、基本原理 通过 HTML 上载文件的基本流程如下图所示。 浏览器端提供了供用户选择提交内容的界面(通常是

2、一个表单),在用户提交请求后,将文件数据和其他表单信息编码并上传至服务器端,服务器端(通常是一个 cgi 程序)将上传的内容进行解码了,提取出 HTML 表单中的信息,将文件数据存入磁盘或数据库。 二、各过程详解 A)填写表单并提交 通过表单提交数据的方法有两种,一种是 GET 方法,另一种是 POST 方法,前者通常用于提交少量的数据,而在上传文件或大量数据时,应该选用 POST 方法。在 HTML 代码中,在

标签中添加以下代码可以页面上显示一个选择文件的控件。 在页面中显示如下(可能随

3、浏览器不同而不同) 可以直接在文本框中输入文件名,也可以点击按钮后弹出供用户选择文件的对话框。 B)浏览器编码 在向服务器端提交请求时,浏览器需要将大量的数据一同提交给 Server 端, 而提交前,浏览器需要按照 Server 端可以识别的方式进行编码,对于普通的表单数据,这种编码方式很简单,编码后的结果通常是 field1=value2&field2=value2&… 的形式,如 name=aaaa&Submit=Submit。 这种编码的具体规则可以在 rfc2231 里查到, 通常使用的表单也是采用这种方式编码的,Servlet 的 API 提供了对这种编码方式解码的

4、支持,只需要调用 ServletRequest 类中的方法就可以得到用户表单中的字段和数据。 这种编码方式( application/x-www-form-urlencoded )虽然简单,但对于传输大块的二进制数据显得力不从心,对于传输这类数据,浏览器采用了另一种编码方式,即 "multipart/form-data" 的编码方式,采用这种方式,浏览器可以很容易的表单内的数据和文件一起。这种编码方式先定义好一个不可能在数据中出现的字符串作为分界符,然后用它将各个数据段分开,而对于每个数据段都对应着 HTML 页面表单中的一个 Input 区,包括一个 content-disposition

5、 属性,说明了这个数据段的一些信息,如果这个数据段的内容是一个文件,还会有 Content-Type 属性,然后就是数据本身。 这里,我们可以编写一个简单的 Servlet 来看到浏览器到底是怎样编码的。 实现流程: · 重载 HttpServlet 中的 doPost 方法 · 调用 request.getContentLength() 得到 Content-Length ,并定义一个与 Content-Length 大小相等的字节数组 buffer 。 · 从HttpServletRequest 的实例 request 中得到一个 InputStream, 并把它读入 buff

6、er 中。 · 使用 FileOutputStream 将 buffer 写入指定文件。 代码清单 // ReceiveServlet.java import java.io.*; import javax.servlet.*; import javax.servlet.http.*; //示例程序:记录下Form提交上来的数据,并存储到Log文件中 public class ReceiveServlet extends HttpServlet { public void doPost(HttpServletRequest request,HttpServletR

7、esponse response) throws IOException, ServletException { //1 int len = request.getContentLength(); byte buffer[] = new byte[len]; //2 InputStream in = request.getInputStream(); int total = 0; int once = 0; while ((total < len) && (onc

8、e >=0)) { once = in.read(buffer,total,len); total += once; } //3 OutputStream out=new BufferedOutputStream( new FileOutputStream("Receive.log",true)); byte[] breaker="\r\nNewLog: -------------------->\r\n".getBytes(); System.out.println(

9、request.getContentType()); out.write(breaker,0,breaker.length); out.write(buffer); out.close(); in.close(); } } · 在使用 Opera 作为浏览器测试时,从指定的文件( Receive.log )中可以看到如下的内容 --_OPERAB__-T/DQLi2fn47+D52OOrpdrz Content-Disposition: form-data; name="id" id00 --_

10、OPERAB__-T/DQLi2fn47+D52OOrpdrz Content-Disposition: form-data; name="file3"; filename="Autoexec.bat" Content-Type: application/octet-stream @echo off prompt $d $t [ $p ]$_$$ --_OPERAB__-T/DQLi2fn47+D52OOrpdrz-- 这里 _OPERAB__-T/DQLi2fn47+D52OOrpdrz 就是浏览器指定的分界符,不同的浏览器有不同的确定分界符的方法,但都需要保证分界符不会

11、在文件内容中出现。 下面是用 IE 进行测试的结果 -----------------------------7d137a26e18 Content-Disposition: form-data; name="name" 123 -----------------------------7d137a26e18 Content-Disposition: form-data; name="introduce" I am... I am.. -----------------------------7d137a26e18 Content-Disposition: form-

12、data; name="file3"; filename="C:\Autoexec.bat" Content-Type: application/octet-stream @echo off prompt $d $t [ $p ]$_$$ SET PATH=d:\pf\IBMVJava2\eab\bin;%PATH%;D:\PF\ROSE98I\COMMON -----------------------------7d137a26e18-- 这里 ---------------------------7d137a26e18 作为分界符。关于分界符的规则可以概况为两条: ·

13、除了最后一个分界符,每个分界符后面都加一个 CRLF 即 '\u000D' 和 '\u000A', 最后一个分界符后面是两个分隔符"--" · 每个分界符的开头也要加一个 CRLF 和两个分隔符("-")。 浏览器采用默认的编码方式是 application/x-www-form-urlencoded ,可以通过指定 form 标签中的 enctype 属性使浏览器知道此表单是用 multipart/form-data 方式编码如: < form action="/servlet/ReceiveServlet" ENCTYPE="multipart/form-data" method=p

14、ost > C)提交请求 提交请求的过程由浏览器完成的,并且遵循 HTTP 协议,每一个从浏览器端到服务器端的一个请求,都包含了大量与该请求有关的信息, 在 Servlet 中,HttpServletRequest 类将这些信息封装起来,便于我们提取使用。 在文件上载和表单提交的过程中,有两个关心的问题,一是上载的数据是是采用的那种方式的编码,这个问题的可以从 Content-Type 中得到答案,另一个是问题是上载的数据量有多少即 Content-Length ,知道了它,就知道了 HttpServletRequest 的实例中有多少数据可以读取出来。 这两个属性,我们都可以直

15、接从 HttpServletRequest 的一个实例中获得,具体调用的方法是 getContentType() 和 getContentLength() 。 Content-Type 是一个字符串,在上面的例子中,增加 System.out.println(request.getContentType()); 可以得到这样的一个输出字符串: multipart/form-data; boundary=---------------------------7d137a26e18 前半段正是编码方式,而后半段正是分界符; 任务分解上述的字符串,取出分界符。 通过 Strin

16、g 类中的方法,我们可以把这个字符串分解,提取出分界符。 String contentType = request.getContentType( ); int start = contentType.indexOf("boundary="); int boundaryLen = new String("boundary=").length(); String boundary = contentType.substring(start+boundaryLen); boundary = "--" + boundary; 判

17、断编码方式可以直接用 String 类中的 startsWith 方法判断。 if(contentType==null || !contentType.startsWith("multipart/form-data")) 这样,我们在解码前可以知道: 编码的方式是否是multipart/form-data 数据内容的分界符 数据的长度 我们可以用类似于 ReceiveServlet 中的方式将这个请求的输入流读入一个长度为 Content-Length 的字节数组,接下来就是将这个字节数组里的内容全部提取出来了。 D)解码 解码对我们来说是整个上载过程最繁琐的一个

18、步骤,经过以上的流程,我们可以得到一个包含有所有上载数据的一个字节数组和一个分界符,通过对 Receive.log 分析,还可以得到每个数据段中的分界符。 而我们要得到以下内容: · 提交的表单中的各个字段以及对应的值 · 如果表单中有 file 控件,并且用户选择了上载文件,则需要分析出字段的名称、文件在浏览器端的名字、文件的 Content-Type 和文件的内容。 字节数组的内容可以分解如下: 具体解码过程也可以分为两个步骤: · 将上载的数据分解成数据段,每个数据段对应着表单中的一个 Input 区。 · 对每个数据段,再进行分解,提出上述要求得到的内容。 这两

19、个步骤主要的操作有两个,一个是从一个数组中找出另一个数组的位置,类似于 String 类中的 indexOf 的功能,另一个是从一个数组中提取出另一个数组, 类似于 String 类中的 substring 的功能,为此我们可以专门写两个方法,实现这种功能。 int byteIndexOf (byte[] source,byte[] search,int start) byte[] subBytes(byte[] source,int from,int end) 为了便于使用,可以从这两个方法中衍生出下列方法 int byteIndexOf (byte[] source,Strin

20、g search,int start) 以一个 String 作为搜索对象参数 String subBytesString(byte[] source,int from,int end) 直接返回一个 String int bytesLen(String s) 返回字符串转化为字节数组后,字节数组的长度 这样,从一个字节数组中,根据标记提取出另一个字节数组可以表示如下: 假设我们已经将数据存入字节数组 buffer 中,分界符存入 String boundary 中 int pos1=0;

21、 //pos1 记录 在buffer 中下一个 boundary 的位置 //pos0,pos1 用于 subBytes 的两个参数 int pos0=byteIndexOf(buffer,boundary,0); //pos0 记录 boundary 的第一个字节在buffer 中的位置 do { pos0+=boundaryLen; //记录boundar

22、y后面第一个字节的下标 pos1=byteIndexOf(buffer,boundary,pos0); if (pos1==-1) break; pos0+=2; //考虑到boundary后面的 \r\n PARSE[(subBytes(buffer,pos0,pos1-2));] //考虑到boundary后面的 \r\n pos0=pos

23、1; }while(true); 其中 PARSE 部分是对每一个数据段进行解码的方法,考虑到 Content-Disposition 等属性,首先定义一个 String 数组 String[] tokens={"name=\"", "\"; filename=\"", "\"\r\n", "Content-Type: ", "\r\n\r\n" }; 对于一个不是文件的数据段,只可能有 tokens 中的第一个元素和最后一个元素,如果是一个文件数据段,则包含所有的元素。第一步先

24、得到 tokens 中每个元素在这个数据段中的位置 int[] position=new int[tokens.length]; for (int i=0;i < tokens.length ;i++ ) { position[i]=byteIndexOf(buffer,tokens[i],0); } 第二步判断是否是一个文件数据段,如果是一个文件 数据段则 position[1] 应该大于0,并且 postion[1] 应该小于 postion[2] 即 position[1] > 0 &&

25、 position[1] < position[2] 如果为真,则为一个文件数据段, 1.得到字段名 String name =subBytesString(buffer,position[0]+bytesLen(tokens[0]),position[1]); 2.得到文件名 String file= subBytesString(buffer,position[1]+bytesLen(tokens[1]),position[2]); 3.得到 Content-Type String contentType=subBytesString(buffer,position[3]+by

26、tesLen(tokens[3]),position[4]); 4.得到文件内容 byte[] b=subBytes(buffer,position[4]+bytesLen(tokens[4]),buffer.length); 否则,说明数据段是一个 name/value 型的数据段, 且name 在 tokens[0] 和 tokens[2] 之间,value 在 tokens[4]之后 //1.得到 name String name =subBytesString(buffer,position[0]+bytesLen(tokens[0]),position[2]); //2

27、得到 value String value= subBytesString(buffer,position[4]+bytesLen(tokens[4]),buffer.length); 回页首 三、具体实现 为便于使用,定义 upload 包,包括以下类: ContentFactory 对从 client 中传来的数据进行解码,并提供一系列 get 方法,从中得到上传的各种信息。 具体接口如下 staticContentFactory getContentFactory (javax.servlet.http.HttpServletRequestreque

28、st) 返回根据当前请求生成的一个 ContentFactory 实例 staticContentFactory getContentFactory (javax.servlet.http.HttpServletRequestrequest, intmaxLength) 返回根据当前请求生成的一个 ContentFactory 实例 FileHolder getFileParameter (java.lang.Stringname) 返回一个 FileHolder 实例,该实例包含了通过字段名为 name 的 file 控件上载的文件信息,如果不存在这个字段或者提交

29、页面时,没有选择上载的文件,则返回 null。 java.util.Enumeration getFileParameterNames () 返回一个 由 String 对象构成的 Enumeration ,包含了 Html 页面窗体中所有 file 控件的 name 属性。 FileHolder[] getFileParameterValues (java.lang.Stringname) 返回一个 FileHolder 数组,该数组包含了所有通过字段名为 name 的 file 控件上载的文件信息,如果不存在这个字段或者提交页面时,没有选择任何上载的文件,则返回一个

30、零元素的数组(不是 null )。 java.lang.String getParameter (java.lang.Stringname) 以 String 类型返回请求的参数的值,如果该参数不存在,则返回为 null 。参数存于提交的表单数据中。 java.util.Enumeration getParameterNames () 返回一个 String 类型的 Enumeration 对象,该对象包含了所有提交请求的参数名称。 java.lang.String[] getParameterValues (java.lang.Stringname) 返回

31、 String 类型的数组,该数组包含了指定名称的参数对应的所有的值,如果参数不存在,则返回为 null。 FileHolder 封装一个文件数据段,可以从中提取文件名, Content-Type 和文件内容等属性。 接口如下: byte[] getBytes () 返回一个文件内容的字节数组 java.lang.String getContentType () 返回该文件的 Content-Type java.lang.String getFileName () 返回该文件在文件上载前在客户端的名称 java.lang.String getPa

32、rameterName () 返回上载该文件时,Html 页面窗体中 file 控件的 name 属性 void saveTo (java.io.Filefile) 把文件的内容存到指定的文件中 void saveTo (java.lang.Stringname) 把文件的内容存到指定的文件中 ContentFactoryException 在 ContentFactory.getContentFactory 方法中可能抛出。 各类的源文件详解代码清单。 回页首 四、使用示例 附录中包含了一个 Servlet 示例,该示例重载了 HttpSe

33、rvlet 的两个方法 ( doGet, doPost ),在浏览器发送 GET 请求时,产生一个表单,在用户提交表单时,将文件和数据上载,并在浏览器端显示出上载文件存盘后的 URL ,以及页面中的各字段的 name 和 value 。该示例及各类在Windows98、jdk1.3和tomcat3.1,浏览器为IE5和Opera3.6的环境下调试通过。 回页首 五、附录 · 代码清单 o 1、ContentFactory.java o 2、FileHolder.java o 3、ContentFactoryException.java o 4、FormUpload.java · 示例及整个 upload 包,以及 javadoc 生成的 API 文档( source.zip ) 参考资料 · RFC1867 Form-based File Upload in HTML · RFC2045/2046 MIME (Multipurpose Internet Mail Extensions) · RFC1806 The Content-Disposition Header · RFC2388 Returning Values from Forms: multipart/form-data

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服