概述

FileUpload能够以多种不同的方式使用,具体取决于应用程序的要求。在最简单的情况下,调用单个方法来解析servlet请求,然后处理解析出来的Item集合。此外也可以自定义FileUpload已完全控制各个Item的存储方式,比如设置缓存目录、直接将接收到的Item以流的形式写入数据库等。

FileUpload依赖于Commons IO,因此类路径下要有Commons IO的jar包。当然采用Maven依赖的方式不用担心,maven会自动下载Commons IO包。

FIleUpload使用

上传文件,注意几个问题:

① form表单内,要添加空间<input type="file" name="myfile">
② form表单的内容格式要定义成multipart/form-data格式:<form action="admin/good_add" method="post" enctype="multipart/form-data">
③ 需要类库:1 commons-io.jar ,2 commons-fileupload-1.3.1.jar

接下来我们看下他的用法。

1 创建工厂类

DiskFileItemFactory factory = new DiskFileItemFactory();

FileItemFactory可以设置内容:

● setRepository(File dir);//设置临时文件存储位置。

● setSizeThreshold(long bytes);//设置请求大小阈值,当请求大于该值时,接收到的数据是缓存在磁盘中的,否则直接缓存到内存中。

● setFileCleaningTracker(FileCleaningTracker pTracker);//设置临时文件清理跟踪器

创建核心类-文件解析对象

ServletFileUpload upload = new ServletFileUpload(DiskFileItemFactory factory);

ServletFileUpload可以设置内容:

● setSizeMax(long bytes);//设置整个请求的最大值,大于该值时,不允许传送。

● setFileMaxSize(long bytes);//设置单个文件的最大值,大于该值时,不允许传送。

● setHeaderEncoding(String charset);//设置读取每个FileItem的头数据的字符编码,不设置时采用request编码,也没有时采用系统默认编码。

● serProgressListener(ProgressListener pListener);//设置上传进度监听器

3 解析request请求-进行文件解析后放在List中,因为这个类库支持多个文件上传,因此把结果会存在List中。

List<FileItem> list = upload.parseRequest(request);

FileItem能够获取的内容:

● getContentType();//获取单个Item的ContentType

● getName();//获取Item本来的文件名,如果不是文件则为null

● getFieldName();//获取Item的field名

● getSize();//获取Item的大小

● get();//将Item转换成字节数组返回

● isInMemory();//Item目前是否存在内存中

● isFormField();//是否是表单域

● getInputStream();//获取输入流,用于读取Item

上传原理和代码分析

上传:将需要上传的资源,发送给服务器,在服务器中保存下来。

下载:下载资源时,将服务器上的某个资源发送给浏览器。

浏览器端:

注意:enctype=multipart/form-data:该属性表明发送的请求体的内容是多表单元素的,通俗点讲,就是有各种各样的数据,可能有二进制数据,也可能有表单数据,等等。

 <form class="form-horizontal" action="${pageContext.request.contextPath }/admin/good_add" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="input_name" class="col-sm-1 control-label">名称</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="input_name" name="name" required="required">
</div>
</div>
<div class="form-group">
<label for="input_name" class="col-sm-1 control-label">价格</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="input_name" name="price">
</div>
</div>
<div class="form-group">
<label for="input_name" class="col-sm-1 control-label">介绍</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="input_name" name="intro">
</div>
</div>
<div class="form-group">
<label for="input_name" class="col-sm-1 control-label">库存</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="input_name" name="stock">
</div>
</div>
<div class="form-group">
<label for="input_file" class="col-sm-1 control-label">封面图片</label>
<div class="col-sm-6">
<input type="file" name="cover" id="input_file" required="required">推荐尺寸: 500 * 500
</div>
</div>
<div class="form-group">
<label for="input_file" class="col-sm-1 control-label">详情图片1</label>
<div class="col-sm-6">
<input type="file" name="image1" id="input_file" required="required">推荐尺寸: 500 * 500
</div>
</div>
<div class="form-group">
<label for="input_file" class="col-sm-1 control-label">详情图片2</label>
<div class="col-sm-6">
<input type="file" name="image2" id="input_file" required="required">推荐尺寸: 500 * 500
</div>
</div>
<div class="form-group">
<label for="select_topic" class="col-sm-1 control-label">类目</label>
<div class="col-sm-6">
<select class="form-control" id="select_topic" name="good.type.id">
<c:forEach items="${typeList }" var="t">
<option value="${t.id }">${t.name }</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-1 col-sm-10">
<button type="submit" class="btn btn-success">提交保存</button>
</div>
</div>
</form>

My Code

使用multipart/form-data会有一个boundary属性,来用将提交的表单数据进行分隔,以用来让服务器知道哪个是我们上传的资源,哪个是普通的表单数据。

 <form action="adctionServlet" method="post" enctype="enctype=multipart/form-data">
描述:<input type="text" name=""/><br/>
图片:<input type="file" name="image"/><br/>
<input type="submit" value="上传"/>
</form>

服务器端:

使用commons-fileupload进行处理上传内容。

 try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory); List<FileItem> list = upload.parseRequest(request);
Goods goods = new Goods();
for (FileItem item : list) { // 判断itme;true-为普通输入项,false-为文件
if (item.isFormField()) { // 设置商品属性
switch (item.getFieldName()) {
case "name":
goods.setName(item.getString("utf-8"));
break;
case "price":
goods.setPrice(Float.parseFloat(item.getString("utf-8")));
break;
case "intro":
goods.setIntro(item.getString("utf-8"));
break;
case "stock":
goods.setStock(Integer.parseInt(item.getString("utf-8")));
break;
case "good.type.id":
goods.setTypeid(Integer.parseInt(item.getString("utf-8")));
break;
}
} else { if (item.getInputStream().available() <= 0) {
continue;
}
// 1-获取文件名;2-获取后缀名;3-根据毫秒值设置新的文件名;4-创建保存路径
String fileName = item.getName();
fileName = fileName.substring(fileName.indexOf("."));
fileName = "/" + System.currentTimeMillis() + fileName;
String path = this.getServletContext().getRealPath("/picture") + fileName; // 读取上传
InputStream in = item.getInputStream();
FileOutputStream out = new FileOutputStream(path);
byte[] buff = new byte[1024];
int len = 0;
while ((len = in.read(buff)) > 0) {
out.write(buff, 0, len);
}
in.close();
out.close(); // 设置商品属性
switch (item.getFieldName()) {
case "cover":
goods.setCover("/picture" + fileName);
break;
case "image1":
goods.setImage1("/picture" + fileName);
break;
case "image2":
goods.setImage2("/picture" + fileName);
break;
}
}
item.delete();
}
} catch (FileUploadException e) {
e.printStackTrace();
}

My Code

上传的各种问题:

1,上传文件名乱码问题:使用servletFileUpload.setHeaderEncoding("UTF-8");或者request.setCharacterEncoding("UTF-8")都可以。

2,表单内容乱码问题:使用getString("utf-8")即可,也就是在获取内容时,就可以设置码表。

3,上传文件同名问题:使用UUID.randomUUID().toString().replace("-", "").获得一个独一无二的32位数字。

4,使用FileUtils.copyInputStreamToFile(is, file);来将内容输出到指定路径文件中去,mkdirs() 自动创建目录

 public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try { //0.5 检查是否支持文件上传 ,检查请求头Content-Type : multipart/form-data
if(!ServletFileUpload.isMultipartContent(request)){
throw new RuntimeException("不要得瑟,没用");
} //1 工厂
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
// 1.1 设置是否生产临时文件临界值。大于2M生产临时文件。保证:上传数据完整性。
fileItemFactory.setSizeThreshold(1024 * 1024 * 2); //2MB
// 1.2 设置临时文件存放位置
// * 临时文件扩展名 *.tmp ,临时文件可以任意删除。
String tempDir = this.getServletContext().getRealPath("/temp");
fileItemFactory.setRepository(new File(tempDir)); //2 核心类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
// 2.1 如果使用无参构造 ServletFileUpload() ,手动设置工厂
//servletFileUpload.setFileItemFactory(fileItemFactory);
// 2.2 单个上传文件大小
//servletFileUpload.setFileSizeMax(1024*1024 * 2); //2M
// 2.3 整个上传文件总大小
//servletFileUpload.setSizeMax(1024*1024*10); //10M
// 2.4 设置上传文件名的乱码
// * 首先使用 setHeaderEncoding 设置编码
// * 如果没有设置将使用请求编码 request.setCharacterEncoding("UTF-8")
// * 以上都没有设置,将使用平台默认编码
servletFileUpload.setHeaderEncoding("UTF-8");
// 2.5 上传文件进度,提供监听器进行监听。
servletFileUpload.setProgressListener(new MyProgressListener()); //3 解析request ,List存放 FileItem (表单元素的封装对象,一个<input>对应一个对象)
List<FileItem> list = servletFileUpload.parseRequest(request); //4 遍历集合获得数据
for (FileItem fileItem : list) {
// 判断
if(fileItem.isFormField()){
// 5 是否为表单字段(普通表单元素)
//5.1.表单字段名称
String fieldName = fileItem.getFieldName();
System.out.println(fieldName);
//5.2.表单字段值 , 解决普通表单内容的乱码
String fieldValue = fileItem.getString("UTF-8");
System.out.println(fieldValue);
} else {
//6 上传字段(上传表单元素)
//6.1.表单字段名称 fileItem.getFieldName();
//6.2.上传文件名
String fileName = fileItem.getName();
// * 兼容浏览器, IE : C:\Users\liangtong\Desktop\abc.txt ; 其他浏览器 : abc.txt
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
// * 文件重名
fileName = UUID.randomUUID().toString().replace("-", "") + fileName;
// * 单个文件夹文件个数过多?
String subDir = StringUtils.getDir(fileName); System.out.println(fileName);
//6.3.上传内容
InputStream is = fileItem.getInputStream();
String parentDir = this.getServletContext().getRealPath("/WEB-INF/upload");
File file = new File(parentDir + subDir,fileName); // 将指定流 写入 到 指定文件中 -- mkdirs() 自动创建目录
FileUtils.copyInputStreamToFile(is, file); //7删除临时文件
fileItem.delete();
}
} } catch (Exception e) {
e.printStackTrace(); throw new RuntimeException(e); }
}

总结上传:

其实理解了也不是很难,就是上传文件后的处理比较麻烦,各种小问题,存储过程最为麻烦。

1、创建工厂类

2、使用核心类,

3、解析request请求,

4、遍历请求体的内容,将上传内容和普通表单内容都获取出来

5、获取到上传内容时,对其存储位置进行设置

@部分转载自:https://www.cnblogs.com/whgk/p/6479405.html

文件上传 - Commons FileUpload介绍的更多相关文章

  1. 文件上传组件FileUpload 以及邮箱搭建JavaMail

     文件上传与下载 1.1 文件上传 案例: 注册表单/保存商品等相关模块! --à 注册选择头像 / 商品图片 (数据库:存储图片路径 / 图片保存到服务器中指定的目录) 文件上传,要点: 前台: 1 ...

  2. 文件的上传Commons FileUpload(web基础学习笔记十六)

    一.表单设置 <form action="<%=request.getContextPath()%>/jsp/admin/doAdd.jsp" enctype=& ...

  3. .JavaWeb文件上传和FileUpload组件使用

    .JavaWeb文件上传 1.自定义上传 文件上传时的表单设计要符合文件提交的方式: 1.提交方式:post 2.表单中有文件上传的表单项:<input type="file" ...

  4. 文件上传(FileUpload控件)

    asp.net 文件上传,大文件上传.   新建一个asp.net页面,在工具栏里拖入 FileUpload 上传控件.一个按钮 Button  !    !     ! 进入Button事件 //- ...

  5. ASP中文件上传组件ASPUpload介绍和使用方法

    [导读]要实现该功能,就要利用一些特制的文件上传组件.文件上传组件网页非常多,这里介绍国际上非常有名的ASPUpload组件 1 下载和安装ASPUpload  要实现该功能,就要利用一些特制的文件上 ...

  6. Jquery-uploadify多文件上传插件使用介绍

    Jquery-uploadify多文件上传插件使用起来非常的给力,在此记录一下使用方法. query-uploadify插件的属性设置 <script src="JS/jquery.m ...

  7. 文件上传使用FileUpload组件进行代码实现

    使用FileUpload组件进行代码实现 实现步骤 1. 获取解析器工厂: DiskFileItemFactory 2. 获取解析器对象: ServletFileUpload 3. 解析request ...

  8. 实现文件上传功能(FileUpload组件)

    文件上传: 项目中经常用到文件上传. 自己实现文件上传,使用文件上传组件fileupload组件 1.指定表单类型为文件上传, enctype=”multipart/form-data” 2.提交方式 ...

  9. SpringMVC框架06——文件上传与下载

    1.文件上传 Spring MVC框架的文件上传是基于commons-fileupload组件的文件上传,只不过Spring MVC框架在原有文件上传组件上做了进一步封装,简化了文件上传的代码实现. ...

随机推荐

  1. 让delphi2010能有delphi7的版面布局

    如何让delphi2010能有delphi7的版面布局呢?答案是肯定的,方法如下: 1)在工具栏点右键,选择components 会看到delphi7中的组件显示面板 2)tools > opt ...

  2. sql还原数据库时候改变数据库名

    需求:在做图书馆数据整合时候,由于有两个校区,用的是分离开的同一个数据库,数据库名字都一样的,现在我要整合在一起,我的想法是把两个数据库先还原到我本地,用写好的脚本整合到一起.所以,我还原两个数据库时 ...

  3. [kuangbin带你飞]专题一 简单搜索 - A - 棋盘问题

    #include<iostream> #include<cstdio> #include<string> #include<vector> #inclu ...

  4. Mac 上的 redis

    Mac下添加redis的环境变量: echo 'export PATH="/usr/local/opt/redis@3.2/bin:$PATH"' >> ~/.bash ...

  5. 11_springmvc之RESTful支持

    一.理解RESTful RESTful架构,就是一种互联网软件架构.它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. RESTful(即Representational Sta ...

  6. python字符串的索引切片和常用操作方法,for循环

    ---恢复内容开始--- 一.字符串的索引与切片 1.索引 s = 'ASDFGHJKL' 有序序列,索引--index:从0开始 s1 = s[0],取出单个元素:A: s1是个全新的字符串和原字符 ...

  7. <day002>Selenium基本操作+unittest测试框架

    任务1:Selenium基本操作 from selenium import webdriver # 通用选择 from selenium.webdriver.common.by import By # ...

  8. 在 my_rootfs 中建立 Linux 目录树

    [arm@localhost my_rootfs]#mkdir bin dev etc home lib mnt proc sbin sys tmp root usr [arm@localhost m ...

  9. 制作windows10系统启动U盘,从零开始。

    1.打开百度,搜索windows下载,选个这个点击进去. 2.会看到下图,然后点击立即下载工具按钮. 3.接下来由于网络的原因,可能需要漫长的等待.会下载一个MediaCreationTool1903 ...

  10. 网络工程师课程---3、IP与路由器(ip地址的主要作用是什么)

    网络工程师课程---3.IP与路由器(ip地址的主要作用是什么) 一.总结 一句话总结: 用来标识一个节点的网络地址 划分网段 1.如何得到ip地址的网段号? ip和子网掩码  化成二进制后取 与运算 ...