JavaWeb之文件上传、下载
时间:2016-12-17 18:07
——文件上传概述
上传不能使用BaseServlet
1、文件上传的作用
例如网络硬盘,就是用来上传和下载文件的。
2、文件上传对表单的限制
1)必须使用表单,而不能是超链接
2)表单的method必须是POST,而不能是GET
3)表单的enctype必须是multipart/form-data
4)在表单中添加type="file",即<input type="file" name="" />
<form action="xxx" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username" /><br/>
照 片:<input type="file" name="photo" /><br/>
<input type="submit" value="上传" />
</form>
3、文件上传对Servlet的限制
1)当表单为enctype="multipart/form-data"时,不能使用request.getParameter()方法,该方法永远返回null。
2)使用ServletInputStream request.getInputStream()来获取完整的请求体。
4、多部件表单结构
1)分割出多个部件,即一个表单项生成一个部件。
2)一个部件中会自己包含请求头和空行以及请求体。
3)普通表单项:
> 一个头:
* Content-Disposition,包含name="xxx",即表单项名称。
> 体就是表单项的值。
4)文件表单项:
> 两个头:
* Content-Disposition,包含name="xxx",即表单项名称,还有一个filename="xxx",表示上传文件的名称。
* Content-Type:它是上传文件的MIME类型,例如:image/jpeg,表示上传的是图片。
> 体就是上传文件的内容。
——commons-fileupload
* commins-fileupload.jar
* 依赖包:commons-io.jar
这个组件会解析request中的上传数据,解析后的结果是一个表单项数据封装到一个FileItem对象中,只需要调用FIleItem对象的方法即可。(多个表单项会封装多个FileItem,即List<FileItem>)
1、上传三个步骤
相关类:
* 工厂类:DiskFileItemFactory
* 解析器:ServletFileUpload
* 表单项:FileItem(该类对应一个表单项)
1)创建工厂:
DiskFileItemFactory factory = new DiskFileItemFactory();
2)创建解析器:
ServletFileUpload sfu = new ServletFileUpload(factory);
3)使用解析器来解析request,得到FileItem集合:
List<FileItem> fileItemList = sfu.parseRequest(request);
2、FileItem类
普通表单项相关方法:
* boolean isFormField()
是否为普通表单项。
true为普通表单项。
false为文件表单项。
* String getFieldName()
返回当前表单项的名称。
* String getString(String charset)
通过指定编码获取表单项的值。
该方法不适用于文件表单项。
必须指定编码。
文件表单项相关方法:
* String getName()
返回上传的文件名称。
* long getSize()
返回上传文件的字节数。
* String getContentType()
获取MIME类型。
* InputStream getInputStream()
返回上传文件对应的输入流。
* void write(File file)
将上传的文件写入指定文件中。
如果file已存在,则会替换目标文件,如果file不存在,则会创建该文件。
——文件上传简单示例
===============================================================================
com.wyc.servlet.UploadServlet
System.out.println("文件大小:" + size);
------------------------------------------------------------------------------------------------------------------------------
form.jsp
===============================================================================
——文件上传细节
1、把上传的文件放到WEB-INF目录下
如果没有把用户上传的文件放到WEB-INF目录下,那么用户就可以通过浏览器直接访问上传的文件,这是非常危险的。
假如说用户上传了一个JSP文件,然后用户再通过浏览器去访问这个JSP文件,那么服务器就会执行JSP文件中的内容,如果在JSP文件中有如下语句:Runtime.getRuntime().exec("shutdown -s -t 1");.........
通常我们会在WEB-INF目录下创建一个upload目录来存放上传的文件,而在Servlet中找到这个目录需要使用ServletContext()的getRealPath(String)方法,例如在项目中有如下语句:
ServletContext servletContext = this.getServletContext();
String uploadPath = servletContext.getRealPath("/WEB-INF/uploads");
其中uploadPath为:G:\tomcat\webapps\FileDemo\WEB-INF\uploads
2、文件名称(完整路径)
上传的文件名称可能是完整路径。
IE6获取的上传文件名称是完整路径,而在其他浏览器获取的上传文件名称只是文件名称而已,浏览器差异的问题还需要处理一下。
例如:C:\file\哈哈.jpg
可以通过分割字符串来获取文件名。
int index = fileName.lastIndexOf("\\");
if(index != -1)
fileName = fileName.substring(index+1);
3、处理文件名称乱码和普通表单项乱码
当上传的文件名称中包含中文时,需要设置编码,commons-fileupload组件为我们提供了两种设置编码的方式:
request.setCharacterEncoding("utf-8");
fileUpload.setHeaderEncoding(String charset); // 这种方式的优先级高于前一种。
commons-fileupload内部会调用request.getCharacterEncoding();来指定编码。
上传文件的文件内容中包含中文:
通常我们不需要关心上传文件的内容,因为我们会把上传文件保存到硬盘上,也就是说,原文件是什么样子,保存到服务器之后还是什么样子。
如果想要在控制台显示上传文件的内容,那么可以使用fileItem.getString(String encoding)来使用指定编码处理字符串。
文本内容和普通表单项内容都是用FileItem类的getString(String encoding)来处理编码。
4、文件重名问题
应该为每个文件名添加前缀名称,这个前缀要保证不能重复,可以使用UUID。
fileName = CommonUtils.getUuid() + "_" + fileName;
===============================================================================
5、一个目录不能存放过多文件(存放目录打散)
一个目录下不应该存放过多的文件,一般一个目录存放1000个文件就是上限了,如果再多,那么打开目录时就会很“卡”。
也就是说,我们需要把上传的文件存放到不同的目录中,但是也不能为每个上传的文件都新建一个目录,这样会导致目录过多,所以我们应该采用某种算法来“打散”存放文件的目录。
方法有很多,例如使用日期来打散,每天生成一个目录,也可以使用文件名的首字母来生成目录,相同首字母的文件放到同一目录下。
日期打散算法:如果某一天上传的文件过多,那么也会出现一个目录文件过多的情况。
首字母打散算法:
例如abc.txt,那么可以把文件保存到a目录下,如果a目录不存在,则创建a目录。
如果文件名是中文的,因为中文过多,所以会导致目录过多的情况。
哈希打散算法:
* 通过文件名称得到一个int值,即调用hashCode()获取哈希值。
* 将int值转换成16进制。
* 获取16进制的前两位用来生成目录,目录为两层:例如1B2C3D4E5F,使用/1/B/ 来保存文件。
该存储方式非常不直观,一般会将文件存放的目录保存起来,以后访问下载时可以直接获取。
===============================================================================
6、上传的单个文件、整个表单的大小限制
限制上传文件的大小很简单,ServletFileUpload类的setFileSizeMax(long)就可以实现了,参数就是上传文件的上限字节数,例如:servletFileUpload.setFileSizeMax(1024 * 10),表示上限为10kb。
该方法一定要在parseRequest()方法之前调用。
一旦上传的文件大小超出了上限,那么就会在执行parseRequest()方法时抛出FileUploadBase.FileSizeLimitExceededException异常。
我们可以在Servlet中获取这个异常,然后想页面输出“上传的文件大小超出限制”。
限制整个表单的大小:
fileUpload.setSizeMax(long size);
该方法必须在parseRequest()方法之前调用。
如果大小超出限制,会抛出FileUploadBase.SizeLimitExceededException异常。
===============================================================================
7、设置缓存大小与临时目录
* 缓存大小:
默认为10kb,当上传文件超出缓存大小时,先将文件保存到硬盘,当文件上传完毕后,再将文件保存。
* 临时目录:
缓存的保存目录。
* 可以通过DiskFileItemFactory的构造方法来指定缓存大小和临时目录
DiskFileItemFactory(int sizeThreshold, File repository)
> 默认的临时目录为:System.getProperty("java.io.tmpdir");,打印后:G:\apache-tomcat-7.0.72\temp
> 例如:new DiskFileItemFactory(1024 * 10, new File("F:/temp"));
// 打印默认临时目录
===============================================================================
——文件下载
被下载的资源必须放到WEB-INF目录下,然后通过Servlet完成下载。
在JSP页面中给出超链接,链接到DownloadServlet,并提供要下载的文件名称,然后在DownloadServlet获取文件的真实路径,然后把文件写入到response.getOutputStream()流中。
1、概述
下载就是向客户端响应字节数据。
之前响应的都是HTML的字符数据。
其实就是把一个文件编程字节数组,使用response.getOutputStream()来将文件响应给浏览器。
2、下载的要求
两个头、一个流
* Content-Type:表示传递给客户端文件的MIME类型。
> 通过文件名称调用ServletContext的getMimeType()方法得到MIME类型。
* Content-Disposition:
> 它的默认值为inline,表示在浏览器窗口中打开(当打不开时会弹框)。
> attachment;filename=xxx:表示类型为附件,并在弹框的界面中显示下载的文件名。
* 流:要下载的文件数据。
> 自己new 一个输入流即可,然后通过IOUtils完成流的数据写入。
——下载示例
——DownloadUtils(下载文件名乱码问题)
显示在下载框中包含中文名称时,会出现乱码。
* FireFox,使用Base64编码。
* 其他大部分浏览器,使用URL编码。
通用方法:filename = new String(filename.getBytes("gbk"), "iso-8859-1");
浏览器能读懂ISO-8859-1编码
public static String fileNameEncoding(String fileName, HttpServletRequest request) throws Exception{
注意:
Base64Encoder并不属于JDK标准库范畴,但是又包含在了JDK中,解决方法:
1、按照如下方法设置Eclipse导入%JAVA_HOME%\jre\lib目录下的rt.jar包即可,Project->Properties,选择Java Build Path设置项,再选择Libraries标签,Add External Jars添加%JAVA_HOME%\jre\lib\rt.jar就可以使用了。
2、MyEclipse —— Preferences —— Java —— Compiler —— Errors/Warnings —— Deprecated and restricted API —— Forbidden reference(access rules): Ignore
——BASE64Encoder、BASE64Decoder
JavaWeb之文件上传、下载的更多相关文章
- JavaWeb实现文件上传下载功能实例解析
转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...
- JavaWeb实现文件上传下载功能实例解析 (好用)
转: JavaWeb实现文件上传下载功能实例解析 转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web ...
- Javaweb学习笔记——上传下载文件
一.前言 在Javaweb中,上传下载是经常用到的功能,对于文件上传,浏览器在上传的过程中是以流的过程将文件传给服务器,一般都是使用commons-fileupload这个包实现上传功能,因为comm ...
- JavaWeb 文件 上传 下载
文件上传下载对于一个网站来说,重要性不言而喻.今天来分享一个JavaWeb方式实现的文件上传下载的小例子. 项目依赖 项目目录 工作流程 文件上传 表单处的设置 服务器端 上传功能的实现 upload ...
- JavaWeb多文件上传及zip打包下载
项目中经常会使用到文件上传及下载的功能.本篇文章总结场景在JavaWeb环境下,多文件上传及批量打包下载功能,包括前台及后台部分. 首先明确一点: 无法通过页面的无刷新ajax请求,直接发下载.上 ...
- JavaWeb:实现文件上传与下载
JavaWeb:实现文件上传与下载 文件上传前端处理 本模块使用到的前端Ajax库为Axio,其地址为GitHub官网. 关于文件上传 上传文件就是把客户端的文件发送给服务器端. 在常见情况(不包含文 ...
- JavaWeb 文件上传下载
1. 文件上传下载概述 1.1. 什么是文件上传下载 所谓文件上传下载就是将本地文件上传到服务器端,从服务器端下载文件到本地的过程.例如目前网站需要上传头像.上传下载图片或网盘等功能都是利用文件上传下 ...
- JavaWeb -- 文件上传下载示例
1. 上传简单示例 Jsp <%@ page language="java" import="java.util.*" pageEncoding=&quo ...
- 转载:JavaWeb 文件上传下载
转自:https://www.cnblogs.com/aaron911/p/7797877.html 1. 文件上传下载概述 1.1. 什么是文件上传下载 所谓文件上传下载就是将本地文件上传到服务器端 ...
- JavaWeb:实现文件上传
JavaWeb:实现文件上传 理解文件上传: 1.上传文件就是把客户端的文件发送给服务器端. 2.HTTP响应的正文部分最常见的是HTML文档,但是也可以是其他任意格式的数据,如图片和声音文件中的数据 ...
随机推荐
- python + mysql 实现表删除数据
实例如下: import pymysqldef Delete_From(): #打开数据库链接 db = pymysql.connect("localhost","roo ...
- React refs 的理解
一.是什么 Refs 在计算机中称为弹性文件系统(英语:Resilient File System,简称ReFS) React 中的 Refs提供了一种方式,允许我们访问 DOM节点或在 render ...
- ThinkPHP中使用Verify类生产验证码不显示的原因
今天在做网站部署的时候,发现登录页面的验证码显示不出来了,而且不报任何错误. 直接通过url访问该操作也不能显示. 后来在网上查找了一些解决方法. 在调用$verify = new \Think\Ve ...
- Java字节码增强技术
简单介绍下几种java字节码增强技术. ASM ASM是一个Java字节码操控框架,它能被用来动态生成类或者增强既有类的功能.ASM可以直接产生class文件,也可以在类被加载入Java虚拟机之前动态 ...
- 01.泛型Generic
1. 基本了解 1.1 什么是泛型? 字面意思:不确定的类型 泛型常用:泛型方法,泛型类,泛型接口,泛型委托 1.2 泛型 T(熟悉) T 的作用,其实就是一个通用的容器,制造它的人开始不指定它是用来 ...
- Xshell 打开时,初始运行卡慢优化方法
我使用的是Xshell 6免费版,有需要的同学可以去这个地址下载:https://www.netsarang.com/download/down_form.html?code=622 一开始安装完Xs ...
- js 倒计时退出
<p>您已提交成功!<span id='submit_second'></span></p> $("#submit_second") ...
- git分支merge冲突 error: you need to resolve your current index first
问题: 执行切换代码分支 git checkout featrue_2019-06-24 ,报错如下: error: you need to resolve your current index fi ...
- Wireshark基础
Wireshark基础 wireshark简介: wireshark是一款用于追踪网络流量的辅助工具,帮助捕获.分析网络封包,并进行分析. 主要功能: 1.网络分析任务 查看网 ...
- python自动化之(自动生成测试报告)
前言: 用python执行测试脚本, 测试报告是记录我们测试过程的问题, 方便我们对整个测试过程的把控. 这里引用的是别人写好的模板, 我们拿过来用就OK, 能力强者可自行编写模板 测试报告图模板: ...