*文件上传*
文件上传:将本地的文件通过流写入到服务器的过程。
文件上传的技术:
JSPSmartUpload :应用在JSP上的文件上传和下载的组件。
FileUpload:应用在Java环境上的文件上传的功能。
Servlet3.0:提供文件上传的功能(前面我们选得都是2.5版本)
Struts2:提供文件上传的功能
文件上传的三个要素:
表单的提交的方式需要是POST
表单中需要有元素,需要有name属性和值。
表单enctype=”multipart/form-data”
写一个JSP,再写一个表单form,method为post提交,设置文件上传项,name属性和值,*Content-Type: application/x-www-form-urlencoded*****是默认的,改为****enctype=”multipart/form-data”,用HTTPWathch进行抓包分析:
没有设置enctype属性
POST /web06/jsp/upload.jsp HTTP/1.1
Accept: text/html, application/xhtml+xml, /
X-HttpWatch-RID: 22006-10011
Referer: http://localhost:8080/web06/jsp/upload.jsp
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
*Content-Type: application/x-www-form-urlencoded*
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 53
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=D51DCB996556C94861B2C72C4D978010
info=info&upload=C%3A%5CUsers%5Cjt%5CDesktop%5Caa.txt
没有文件上传中的文件的具体内容
设置enctype属性:
POST /web06/jsp/upload.jsp HTTP/1.1
Accept: text/html, application/xhtml+xml, /
X-HttpWatch-RID: 22006-10026
Referer: http://localhost:8080/web06/jsp/upload.jsp
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
*Content-Type: multipart/form-data;* boundary=—————————7e139d10110a64
Accept-Encoding: gzip, deflate
Host: localhost:8080
Content-Length: 322
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=D51DCB996556C94861B2C72C4D978010
—————————–7e139d10110a64
Content-Disposition: form-data; name=”info”
aaa
—————————–7e139d10110a64
Content-Disposition: form-data; name=”upload”; filename=”C:\Users\jt\Desktop\aa.txt”
Content-Type: text/plain
hello world!!!
—————————–7e139d10110a64–
—————————–7e139d10110a64代表分割线,将内容分割(分为2块就是三个分割线),–代表结束
文件上传的原理分析:
//普通项的aaa是jsp页面上写的名字。普通项就是表单中的其他内容,文件上传项是文件上传的相关内容。
进行一个文件的上传:
1.引入文件上传的相关的jar包
2.编写文件上传的JSP页面
3.编写文件上传的Servlet
上传的内容没有在工程里,而是直接在文件下。
文件上传的API
1.DiskFileItemFactory:磁盘文件项工厂
构造方法:
DiskFileItemFactory()和DiskFileItemFactory(int sizeThreshold,File repostory)
sizeThreshold:设置文件上传的缓冲区的大小,默认值为10kb。
repository:设置文件上传过程中产生临时文件(如果超过了缓冲区的大小,就会产生临时文件)存放的路径。
方法:
setSizeThreshold():设置缓冲区的大小
setRepository():设置临时文件存放的路径
举例代码:
上传的文件如果没有超过缓冲区的大小,会直接在上传的目标文件夹下上传成功;如果超过了缓冲区的大小,会在你设定的临时文件下有一个TMP文件,当上传成功时,目标文件夹下会有一个文件,这个TMP文件也不会消失,用来续传或者其他操作。
2.ServletFileUpload:核心解析类
构造方法:
方法:
判断表单的enctype属性是否正确:
解析Request对象,返回一个List集合(每个部分的对象FileItem):
设置单个文件的大小:
设置上传的文件的总大小:
设置中文文件名上传的乱码的问题(一般不会出现):
设置监听文件上传的进度:
3.FileItem文件项
方法:
判断表单项是普通项还是文件上传项。如果为true代表是普通项:
普通项的方法:
获得普通项的名称:
获得普通项的值:
文件上传项的方法:
获得文件上传的文件名的方法:
获得文件上传的文件内容的方法:
获得文件上传的文件的大小:
删除文件上传过程中的临时文件:
JS控制多文件上传:
文件上传兼容浏览器问题:如果使用IE老版本的浏览器会出现一个文件名称获取错误问题。IE老版本获取文件名称的时候,会带有路径。
一般的浏览器获得的filename都是aa.txt,但是老版本的IE浏览器是会获得全路径的文件名,会造成报错。
解决:
//检索\最后出现的坐标,当这个坐标存在的时候,截取这个左边开始到结束的内容
文件上传同一个目录下文件同名问题:张三向服务器上传了一个文件aa.txt内容是hello world。李四向服务器上传了一个文件aa.txt内容hello Java。后上传的文件将先上传的文件覆盖了。
使用唯一文件名进行解决:
UUID的randomUUID方法toString后得到的是一个包含-的字符串(由数字,字母和-组成)
文件上传同一个目录下文件过多的问题:现在所有的用户都上传文件,如果网站访问量比较大,如果都上传到同一个目录下,在同一个目录下存放的文件太多了,也会对程序有影响(其实打开该目录的时候,都会很卡,更别说读写操作)。
解决方法:
进行目录分离:
按时间分离 :按月、周、天、小时。
按用户分离 :按张三、李四。
按个数分离 :一个目录下存放3000个文件。
*按目录分离算法*****分离**** *:按照某种特定算法进行分离。*
*上传一个文件,得到一个唯一的文件名。*
*唯一文件名获取其hashCode值。—–int类型的值(32位*****,**无论正负**)****
*让hashCode的值 & 0xf;—–得出的这个值作为一级目录。*
*让hashCode右移4位 & 0xf;—-得出的这个值作为二级目录。*
*以此类推。*
*分析算法:*
每级目录下又可以划分为:0000-1111有16个子目录
代码实现:
一般情况下,服务器是不会关闭的。因为服务器关闭后,会发现存放的上传文件都不见了,所以一般不关闭服务器,或者直接将上传的文件存入到本地磁盘中。
*文件下载*
文件下载:将服务器上的一个文件,通过流写入到客户端上。
文件下载的方式:
1.使用超链接的方式实现文件的下载:
在超链接
*注意:超链接的方式,如果浏览器不能识别这种格式的文件,*****就会**提示下载,**点击确定,就会下载。**如果支持该格式的文件,**就会*****直接打开。*
*2.*****通过手动编写代码的方式实现文件的下载**(**无论浏览器支持不支持该格式的文件,都会询问是否下载,点击确定后就是下载*****)*
*设置两个头和一个流*****:****
*Content-Type* *:文件的MIME的类型*****(**可以获取到**)****
*Content-Disposition* *:浏览器支持该格式的文件,提示下载*****(**固定的格式**)****
*设置代表该文件的输入流*****(输出流是固定**的是** **response.getOutputStream()**)****
文件下载的页面
文件下载的Servlet
中文文件的下载:(出现乱码问题)
因为不同的浏览器对中文文件的下载的编码不一样的:
IE浏览器采用的是URL编码
Firefox浏览器采用的是Base64编码
所以需要判断客户端使用的浏览器的类型:User-Agent请求头可以获得客户端浏览器信息。
写一个工具类的base64编码方法,再调用这个方法进行转换,因为这个编码方法进行了加密。
案例:给定目录下的文件下载
需求:给定一个目录(这个目录可以是任意盘符下的任意路径—这个路径下有多少级目录,每级目录中有多少个文件都是未知的)。将这个路径中的文件显示到页面上,在页面上给每个文件都提供相应的下载的链接,当点击这个链接的时候,对该文件进行下载。
分析:
树形结构的遍历,使用队列:根节点都入队然后出队,最后剩余的是叶节点:6 7 8 9 10
文件列表显示的代码实现:
下载代码的实现:
中文名字的文件经过IE浏览器编码时,会将其中的空格转换为加号,所以在这里需要将其中的加号再转换为空格。