JavaWeb 之文件上传
1. 文件上传的要求
1.1 上传对表单的限制
method="post";enctype="multipart/form-data";- 表单中需要添加文件表单项:
<input type="file" name="xxx"/>.
1.2 上传对 Servlet 的限制
request.getParameter("xxx")方法返回的是字符串类型, 所以在表单中有
enctype="multipart/form-data"时, 该方法作废了, 因为它永远都返回 null.- 应该使用
ServletInputStream request.getInputStream(), 返回结果中包含整个请求体. - 上传不能使用 BaseServlet,因为BaseServlet 内部调用了
getParameter()方法.
2. 多部件表单体

- 一个表单被分割出多个部件,即一个表单项一个部件;
- 一个部件中自己包含请求头和空行, 以及请求体;
- 普通表单项
- 包含一个请求头:
Content-Disposition:xxx; name="表单项名称"; - 请求体就是表单项的值.
- 包含一个请求头:
- 文件表单项
- 包含两个请求头:
Content-Disposition:xxx; name="表单项名称"; filename="上传文件的名称";Content-Type: 上传文件的 MIME 类型;- 请求体就是上传文件的内容.
3. 相关 jar 包
commons-fileupload.jarcommons-io.jar- 这个组件会解析 request 中的上传数据, 解析后的结果是,一个表单项数据封装到一个 FileItem 对象中.
我们只需要调用 FileItem 的方法即可.
4. 上传三步
4.1 上传涉及的相关类
- 工厂类:
DiskFileItemFactory; - 解析器类:
ServletFileUpload; - 表单项类:
FileItem;
4.2 具体步骤
- 创建工厂:
DiskFileItemFactory factory = new DiskFileItemFactory(); - 创建解析器:
ServletFileUpload sfu = new ServletFileUpload(factory); - 使用解析器来解析 request, 得到FileItem集合:
List<FileItem> fileItemList = sfu.parseRequest(request);
4.3 FileItem 对象中的方法 (commons-fileupload API)
boolean isFormField(): 是否为普通表单项. true,表示为普通表单项; false,表示为文件表单项;String getFieldName(): 返回当前表单项的名称;String getString(String charset): 返回表单项的值, charset 默认值为 "utf-8";String getName(): 返回上传文件的名称;long getSize(): 返回上传文件的字节数;InputStream getInputStream(): 返回上传文件对应的输入流;void write(File destFile): 把上传文件的内容保存到指定的文件中;String getContentType(): 获取上传文件的 MIME 类型;
5. 上传的细节
5.1 文件必须保存到 WEB-INF 下!
- 目的是不让浏览器直接访问到.
5.2 文件名称相关问题
- IE6 浏览器上传的文件名称是绝对路径(包含磁盘的路径),需要将磁盘部分切割, 例如: "c:\files\a.jpg";
- 文件名乱码或普通表单项乱码:
request.setCharacterEncoding("utf-8"), fileupload 内部会调用request.getCharacterEncoding()方法;servletFileUpload.setHeaderEncoding("utf-8"), 这种方式的优先级高于前一种.
- 文件同名问题: 需要为每个文件添加名称前缀, 为了保证不重复, 可以使用 uuid
filename = CommonUtils.uuid()+"_"+filename;
5.3 目录打散
- 不能在一个目录下存放过多文件
- 首字母打散: 使用文件的首字母作为目录名称; 不方便操作中文的文件名
- 时间打散: 使用当前日期作为目录;
- 哈希打散:
- 通过文件名称获得 int 值, 即调用
hashCode(); - 把 int 值转换成十六进制 "0~9 和 A ~ F";
- 获取十六进制的前两位用来生成目录, 目录为两层! 例如: "1B2C3D4E5F", /1/B 保存文件.
- 通过文件名称获得 int 值, 即调用
5.4 上传文件的大小限制
单个文件的大小限制
sfu.setFileSizeMax(100 * 1024): 表示限制单个文件大小为 100K;- 必须在
parseRequest()方法之前调用; - 如果上传的文件超出限制, 在 parseRequest() 方法执行时, 会抛出异常!!
FileUploadBase.FileSizeLimitExceedeException.
整个请求所有数据大小限制
sfu.setSizeMax(1024 * 1024): 表示限制整个表单大小为 1M;- 必须在
parseRequest()方法之前调用; - 如果上传的文件超出限制, 在 parseRequest() 方法执行时, 会抛出异常!!
FileUploadBase.SizeLimitExceededException.
5.5 缓存大小与临时目录
- 缓存大小: 上传文件超出多大时, 才向硬盘保存! 默认 10KB;
- 临时目录: 向硬盘的什么目录保存;
- 设置缓存大小和临时目录:
new DiskFileItemFactory(20 * 1024, new File("F:/temp"))
// 目录打散
public void UploadServlet extends HttpServlet{
public void doPost(HttpServletRequest request, HttpServletResponse resp)
throws ServletException, IOException{
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;utf-8");
// 文件上传三步
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(factory);
try{
List<FileItem> fileItemList = sfu.parseRequest(request);
// 获取照片文件表单项
FileItem fi = fileItemList.get(1);
// 得到保存上传文件的根路径
String root = this.getServletContext().getRealPath("/WEB-INF/files/");
// 得到文件名
String filename = fi.getName();
//处理文件名的绝对路径问题
int index = filename.lastIndexOf("\\");
if(index != -1){
filename = filename.substring(index+1);
}
// 给文件名添加 uuid 前缀, 处理文件同名问题
String savename = CommonUtils.uuid()+"_"+filename;
// 得到文件名的 hashCode, 生成两层目录
int hCode = filename.hashCode();
String hex = Integer.toHexString(hCode);
File dirFile = new File(root,hex.charAt(0)+"/"+hex.charAt(1));
// 如果目录不存在, 创建目录链
dirFile.mkdirs();
// 创建目标文件
File destFile = new File(dirFile,savename);
// 保存
fi.save(destFile);
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
参考资料:
JavaWeb 之文件上传的更多相关文章
- JavaWeb:实现文件上传
JavaWeb:实现文件上传 理解文件上传: 1.上传文件就是把客户端的文件发送给服务器端. 2.HTTP响应的正文部分最常见的是HTML文档,但是也可以是其他任意格式的数据,如图片和声音文件中的数据 ...
- JavaWeb实现文件上传下载功能实例解析
转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...
- JavaWeb:实现文件上传与下载
JavaWeb:实现文件上传与下载 文件上传前端处理 本模块使用到的前端Ajax库为Axio,其地址为GitHub官网. 关于文件上传 上传文件就是把客户端的文件发送给服务器端. 在常见情况(不包含文 ...
- JavaWeb实现文件上传下载功能实例解析 (好用)
转: JavaWeb实现文件上传下载功能实例解析 转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web ...
- 使用传统javaweb进行文件上传
使用传统文件上传方式 1.配置依赖 <properties> <project.build.sourceEncoding>UTF-8</project.build.sou ...
- JavaWeb多文件上传及zip打包下载
项目中经常会使用到文件上传及下载的功能.本篇文章总结场景在JavaWeb环境下,多文件上传及批量打包下载功能,包括前台及后台部分. 首先明确一点: 无法通过页面的无刷新ajax请求,直接发下载.上 ...
- 深入分析JavaWeb Item40 -- 文件上传和下载
在Web应用系统开发中,文件上传和下载功能是很经常使用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传.浏览器在上传的过程中是将文件以流的形式提交到server端的.假设 ...
- javaweb大文件上传
本文主要关于利用html表单上传文件的后台代码实现. 需要用到两个工具类Apache commons-fileupload和commons-io. 注意要校验是否选择文件上传,最开始写的时候没有加上校 ...
- javaWeb实现文件上传与下载 (转)
文件上传概述 实现web开发中的文件上传功能,需完成如下二步操作: 在web页面中添加上传输入项 在servlet中读取上传文件的数据,并保存到本地硬盘中. 如何在web页面中添加上传输入项? < ...
随机推荐
- C# 播放H264裸码流
要播放H264裸码流,可以分拆为以下三个工作: 1.解码H264裸码流获取YUV数据 2.将YUV数据转换为RGB数据填充图片 3.将获取的图片进行显示 要完成工作1,我们可以直接使用海思的解码库,由 ...
- Git使用笔记2
工作必备: [更新master] git checkout master git pull git checkout zyb/FirstCommit git merge master //git re ...
- PV、UV、GMV
原文地址:电商术语:客单价.UV.PV.转化率.销售额作者:馨闻莲博 UV(独立访客):Unique Visitor,访问您网站的一台电脑客户端为一个访客.00:00-24:00内相同的客户端只会被计 ...
- 组播和广播的概念,IGMP的用途
1.组播和广播的概念 1) 组播 主机之间的通讯模式,也就是加入了同一个组的主机可以接收到此组内的所有数据,网络中的交换机和路由器只向有需求者复制并转发其所需数据. 主机可以向路由器请求加入或退出某个 ...
- 使用Nginx的proxy_cache缓存功能取代Squid(转)
Nginx从0.7.48版本开始,支持了类似Squid的缓存功能.这个缓存是把URL及相关组合当作Key,用md5编码哈希后保存在硬盘上,所以它可以支持任意URL链接,同时也支持404/301/302 ...
- atitit.TokenService token服务模块的设计
atitit.TokenService token服务模块的设计 1. Token的归类1 2. Token的用途2 2.1. 访问控制2 2.2. 编译原理术语)编辑2 2.3. 数据处理2 1. ...
- Atitit.输入法配置说明v1 q229
Atitit.输入法配置说明v1 q229 //------------------------------------------------------ // IME设置 //-------- ...
- 红茶一杯话Binder (初始篇)
1 什么是Binder? 简单地说,Binder是Android平 台上的一种跨进程交互技术.该技术最早并不是由Google公司提出的,它的前身是Be Inc公司开发的OpenBinder,而且在Pa ...
- ajax请求后台返回map类型并如何展示
前台jsp或者ftl文件接收返回结果: <input type="hidden" name="selectedModelListStr" id=" ...
- 转:C++ 关键字 inline详细介绍
1. 内联函数 在C++中我们通常定义以下函数来求两个整数的最大值: int max(int a, int b) { return a > b ? a : b; } 为这么一个小的操作定义一个 ...