**文件上传的概述**
1.了解什么是文件上传
2.文件上传需要大家记住编写客户端需要有3个注意事项。
3.什么是文件上传
* 把本地的文件保存到服务器端
4.做文件上传,该怎么做?
* 客户端
* 选择一个要上传的文件
* 需要提供文件的选择输入框(<input type="file">)
* 注意:如果完成文件的上传,必须有3点注意事项的
* 编写表单,method="post" 必须是post
* 表单中还有一个属性,enctype="multipart/form-data"
* 编写文件的选项框 <input type="file" name="必须要指定,名称可以任意">
* 服务器端
* 把上传的文件写入到某个指定的文件夹下

----------
**Fileupload文件上传的组件**
1.由apache提供的开源的jar包
* 导入开发的jar包
* commons-fileupload-1.2.1.jar
* commons-io-1.4.jar
2.入门的开发
* 开发的步骤,开发的步骤比较固定

----------
**文件上传入门案例**
1.编写入门的案例,目的:让大家来熟悉开发的步骤,使用一些对象和方法,后面讲解。
2.文件上传的案例步骤
* 客户端
* 注意3个注意事项
* 服务器端
* 采用的是FileUpload文件上传的组件,不要忘记导入开发的jar包。
* 创建工厂类,生成对象
* 创建核心解析类,解析request请求,获取到文件项(FileItem)
* 操作FileItem类的方法就可以完成文件的上传了
----------
### FileUpload组件的类和方法 ###
----------
**DiskFileItemFactory类**
1.DiskFileItemFactory:代表磁盘文件项工厂类,作用:用来生产FileItem对象的。
2.方法
* DiskFileItemFactory() -- 空的构造经常使用的。
* DiskFileItemFactory(int sizeThreshold, java.io.File repository)
* sizeThreshold -- 设置上传文件的缓冲区的大小,如果不指定,有默认值是10K
* repository -- 设置临时文件的存储目录,如果上传的文件,超过了缓冲区的大小,产生临时文件,设置临时文件存储的目录。
* void setSizeThreshold(int sizeThreshold) -- 设置缓冲区的大小
* void setRepository(java.io.File repository) -- 设置临时文件的存储目录(上传的文件超过了缓冲区的大小,产生临时文件)
3.总结
* 上述的这两个方法,如果不设置都有默认值的。
----------
**ServletFileUpload类(解析request)**
1.ServletFileUplod 代表的文件上传的类,作用:用来解析request请求。
2.方法
* ServletFileUpload(FileItemFactory fileItemFactory)
* static boolean isMultipartContent(javax.servlet.http.HttpServletRequest request) -- 判断表单的enctype值设置的是否正确
* java.util.List parseRequest(javax.servlet.http.HttpServletRequest request) -- 解析request请求,返回的是List集合
* void setHeaderEncoding(java.lang.String encoding) -- 解决中文文件名称乱码的问题。
* void setFileSizeMax(long fileSizeMax) -- 设置单个上传文件的大小
* void setSizeMax(long sizeMax) -- 设置总大小
3.总结(掌握)
* parseRequest(request) -- 解析request请求
* setHeaderEncoding() -- 解决中文乱码问题呢
* setSizeMax() -- 设置上传文件的总大小
* void setFileSizeMax()
----------
**FileItem接口(文件项)**
1.FileItem类:代表文件项(普通表单项(文本框、密码、单选),又有可能文件的上传项)
2.方法
* boolean isFormField()
* 判断当前的fileItem对象是否是普通表单项还是文件上传项?如果返回true,说明是普通表单项,如果是false,是文件上传项
* 如果是普通表单项(文本框 密码框 复选框 单选框 下拉列表)
* java.lang.String getFieldName() -- 获取的表单中的name属性的值(例如:filedesc)
* java.lang.String getString() -- 获取到用户输入的值(没有解决乱码的问题)
* java.lang.String getString(String encoding) -- 获取到用户输入的值(解决中文乱码问题)
* 如果是文件上传项
* java.lang.String getName() -- 获取的上传文件的名称(ServletFileUpload类中setHeaderEncoding()解决中文乱码)
* java.io.InputStream getInputStream() -- 获取到上传文件的输入流
* void write(java.io.File file) -- 直接写入文件
* void delete() -- 删除临时文件的(注意:删除的代码需要放在流关闭之后)
3.总结
* 上述所有
----------
**文件上传存在的问题**
1.第一个问题:如果使用的是IE6浏览器,存在问题。
* 如果是IE6的浏览器,获取的文件的名称是:C:\class\resource\hello.txt
* 如果浏览器是IE的一些版本(IE6肯定存在该问题),如果使用的是IE6版本的浏览器,选择文件的时候,选择完文件,点击上传。
* 在Servlet中获取到的文件名称是包含文件的路径的。
2.第二个问题:request.getParameter()方法已经不能获取到表单的内容了。(重要的)
* 使用request对象的时候,request.getParameter()方法,在文件上传中,使用的enctype="multipart/form-data"方式,那么request.getParameter()获取不到值了。
3,注意; request.getParameter()已经不能获取到值了!!!
upload.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>文件的上传</h3>
<form action="${pageContext.request.contextPath }/upload" method="post" enctype="multipart/form-data">
文件描述:<input type="text" name="filedesc"/><br/>
文件上传:<input type="file" name="upload"/><br/>
<input type="submit" value="上传"/>
</form>
</body>
</html>
UploadServlet:
public class UploadServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/**
* 1.创建一个工厂类
* 2.创建能解析request对象的类
* 3.解析request请求
* 4.返回的是List集合
* 5.遍历集合,获取到每一个FileItem
* 6.操作FileItem中方法完成文件的上传
*/
//判断,表单的enctype属性值是否设置正确,返回true,说明设置正确。返回false,不正确
if(!ServletFileUpload.isMultipartContent(request)){
//说明设置不正确
throw new RuntimeException("亲,您没有设置正确的enctype属性的值");
}
//1.创建工厂类
DiskFileItemFactory factory=new DiskFileItemFactory();
//设置缓冲区的大小 设置2M
factory.setSizeThreshold(2*1024*1024);
//设置临时文件的存储目录
String tempPath=this.getServletContext().getRealPath("/temp");
System.out.println(tempPath);
//创建文件目录
File tempFile=new File(tempPath);
factory.setRepository(tempFile);
//2.创建能解析request对象的类
ServletFileUpload upload=new ServletFileUpload(factory);
//设置头的编码,解决中文文件名称乱码的问题
upload.setHeaderEncoding("utf-8");
//设置文件上传的总大小 4M
upload.setSizeMax(4*1024*1024);
try {
//3.解析request请求
//4.返回的是List集合
List<FileItem> list=upload.parseRequest(request);
//5.遍历集合,获取到每一个FileItem
for (FileItem fileItem : list) {
//需要判断,当前的fileItem是否是文件描述还是文件上传
//isFormField(),返回true,说明表单的字段(text,password,checkbox,radio)
if(fileItem.isFormField()){
//获取表单中name属性的值
String name=fileItem.getFieldName();
//文件描述,获取用户输入的值
String value= fileItem.getString();
String value_=fileItem.getString("UTF-8");
System.out.println(name+":::"+value+value_);
}else{
//返回false,说明type="file" 说明是文件上传,需要获取用户上传的文件的文件名称
String fileName=fileItem.getName();
//生成唯一的文件的名称
String uuid=UUID.randomUUID().toString();
//名称完全换掉hello.txt --> ffggerwefd.txt
int i=fileName.lastIndexOf(".");
//文件的后缀名
String lastName=fileName.substring(i);
String uuidName=uuid+"_"+lastName;
//获取到的是文件的输入流
InputStream in=fileItem.getInputStream();
//获取upload文件夹的绝对路径
String path=this.getServletContext().getRealPath("/upload");
System.out.println("upload文件夹的绝对路径:"+path);
//创建输出流
OutputStream out=new FileOutputStream(path+"/"+uuidName);
byte[] by=new byte[1024];
int len=0;
while((len=in.read(by))!=-1){
out.write(by, 0 ,len);
}
out.close();
in.close();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
**多文件上传(js控制多个上传输入项)**
1.多文件上传
* 需求:点击添加按钮,生成多个文件的上传项。点击删除的按钮,删除该个上传项。点击上传按钮,把选择的所有的文件上传到服务器端。
* 前台和后台
moreupload.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.8.3.js"></script>
<script type="text/javascript">
$(function(){
$("input[type='button']").click(function(){
//创建div
var $div=$("<div></div>");
//创建选择框
var $input=$("<input type='file' name='upload'/>");
var $del=$("<input type='button' value='删除'/><br/>");
//给删除按钮绑定事件
$del.click(function(){
//删除一行,小div
$(this).parent().remove();
});
$div.append($input);
$div.append($del);
//生成的小div存入大的div
$("#divId").append($div);
});
});
</script>
</head>
<body>
<h3>多文件的上传</h3>
<form action="${pageContext.request.contextPath }/upload" method="post" enctype="multipart/form-data">
<input type="button" value="添加" />
<input type="submit" value="上传"/>
<!-- div,存放生成文件的选择项 -->
<div id="divId"></div>
</form>
</body>
</html>
案例:上传图书封面
AddServlet:
/**
* 添加商品(包含文件的上传)
* @author mjl
*
*/
public class AddProduct extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
DiskFileItemFactory factory=new DiskFileItemFactory();
ServletFileUpload upload=new ServletFileUpload(factory);
//解决中文文件名称乱码问题
upload.setHeaderEncoding("utf-8");
//创建一个Map,存入用户输入的值
Map<String,String> map=new HashMap();
Product product=new Product();
String uuidName=null;
try {
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem : list) {
if(fileItem.isFormField()){
//获取到每个表单项的name的值
String name=fileItem.getFieldName();
//获取到用户输入的值
String value=fileItem.getString("utf-8");
//存入到map集合 map: pname 故事会 price 10
map.put(name, value);
}else{
String fileName=fileItem.getName();
if(fileName!=null && !fileName.trim().isEmpty()){
String uuid=MyUUIDUtils.getUUID();
int i=fileName.lastIndexOf(".");
String lastName=fileName.substring(i);
//唯一的文件名称
uuidName=uuid+lastName;
InputStream in=fileItem.getInputStream();
String path=this.getServletContext().getRealPath("/bookcover");
System.out.println(path);
OutputStream out=new FileOutputStream(path+"/"+uuidName);
int len=0;
byte[] by=new byte[1024];
while((len=in.read(by))!=-1){
out.write(by, 0, len);
}
out.close();
in.close();
fileItem.delete();
}
}
}
//使用BeanUtils来封装数据
BeanUtils.populate(product, map);
product.setImgUrl(uuidName);
ProductService ps=new ProductService();
ps.save(product);
//如果添加成功了,跳转查询所有商品的方法
response.sendRedirect(request.getContextPath()+"/product?method=findAll");
} catch (Exception e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
文件下载:
download.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>文件下载的页面</h3>
<h4><a href="${pageContext.request.contextPath }/download?filename=大二.jpg">大二.jpg</a></h4>
<h4><a href="${pageContext.request.contextPath }/download?filename=guoguo.jpg">guoguo.jpg</a></h4>
<h4><a href="${pageContext.request.contextPath }/download?filename=wangwang.txt">wangwang.txt</a></h4>
</body>
</html>
DownloadServlet:
/**
* 文件的下载
* @author mjl
*
*/
public class DownloadServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//先获取文件的名称
String filename=request.getParameter("filename");
//两个头(响应头),一个流(文件的输入流)
//content-Type 代表要下载文件的MIME的类型 txt=text/plain jpg=image/jpeg
//response.senContentType("text/html;charset=utf-8");
String mimeType=getServletContext().getMimeType(filename);
System.out.println("文件的MIME类型:"+mimeType);
response.setContentType(mimeType);
//弹出下载的窗口 Content-Disposition 值 attachment;filenmae=加上文件名称
response.setHeader("Content-Disposition", "attachment;filename="+filename);
//获取download的路径
String path=this.getServletContext().getRealPath("/download");
InputStream in=new FileInputStream(path+"/"+filename);
//使用response对象,响应
OutputStream out=response.getOutputStream();
byte[] by=new byte[1024];
int len=0;
while((len=in.read(by))!=-1){
out.write(by,0,len);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}