本次上传与下载使用传统的servlet
一、前置知识及环境搭建
当提交的表单是文件上传表单时,那么对Servlet也是有要求的。
首先我们要肯定一点,文件上传表单的数据也是被封装到request对象中的。
request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。
这时可以使用request的getInputStream()方法获取ServletInputStream对象,它是InputStream的子类,这个ServletInputStream对象对应整个表单的正文部分(从第一个分隔线开始,到最后),这说明我们需要的解析流中的数据。当然解析它是很麻烦的一件事情,而Apache已经帮我们提供了解析它的工具:commons-fileupload
commons-fileupload
为什么使用fileupload:
上传文件的要求比较多,需要记一下:
必须是POST表单;
表单的enctype必须是multipart/form-data;
在表单中添加file表单字段,即
Servlet的要求:
不能再使用request.getParameter()来获取表单数据
可以使用request.getInputStream()得到所有的表单数据,而不是一个表单项的数据
这说明不使用fileupload,我们需要自己来对request.getInputStream()的内容进行解析
1、fileupload概述
fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()
fileupload组件需要的JAR包有:
commons-fileupload.jar,核心包
commons-io.jar,依赖包
2、fileupload简单应用
fileupload的核心类有:DiskFileItemFactory、ServletFileUpload、FileItem
使用fileupload组件的步骤如下:
1.创建工厂类DiskFileItemFactory对象
DiskFileItemFactory factory = new DiskFileItemFactory();
2.使用工厂创建解析器对象
ServletFileUpload fileUpload = new ServletFileUpload(factory);
3.使用解析器来解析request对象
List list = fileUpload.parseRequest(request);
DiskFileItemFactory 磁盘文件项工厂类
public DiskFileItemFactory(int sizeThreshold, File repository)
构造工厂时,指定内存缓冲区大小和临时文件存放位置
public void setSizeThreshold(int sizeThreshold)
设置内存缓冲区大小,默认10K
public void setRepository(File repository)
设置临时文件存放位置,默认System.getProperty(“java.io.tmpdir”).
内存缓冲区: 上传文件时,上传文件的内容优先保存在内存缓冲区中,当上传文件大小超过缓冲区大小,就会在服务器端产生临时文件
临时文件存放位置: 保存超过了内存缓冲区大小上传文件而产生临时文件 ,产生临时文件可以通过 FileItem的delete()方法删除
FileItem 表示文件上传表单中 每个数据部分
隆重介绍FileItem类,它才是我们最终要的结果。一个FileItem对象对应一个表单项(表单字段)。一个表单中存在文件字段和普通字段,可以使用FileItem类的isFormField()方法来判断表单字段是否为普通字段,如果不是普通字段,那么就是文件字段了
FileItem类
注意事项:因为文件上传表单采用编码方式multipart/form-data 与传统url编码不同,所有getParameter ()方法不能使用 setCharacterEncoding()无法解决输入项乱码问题
ServletFileUpload 文件上传核心类
maven依赖包如下,jar包可在apache官网下载
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.0.1</version>
</dependency>
二、文件上传
jsp页面
<h1>传统文件上传</h1>
<form action="${pageContext.request.contextPath}/File/file" method="post" enctype="multipart/form-data">
用户:<input type="text" name="username"><br/>
密码:<input type="password" name="password"><br/>
上传文件:<input type="file" name="file1"><br/>
上传文件:<input type="file" name="file2"><br/>
<input type="submit" value="提交">
</form>
<div>
<h1>传统下载文件</h1>
<a href="${pageContext.request.contextPath}/Files/load?path=事务.png" >download文件 </a>
</div>
String existPath = request.getServletContext().getRealPath("/WEB-INF/upload");
//使用Apache文件上传组件处理文件上传步骤:
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory);
//解决上传文件名的中文乱码
fileUpload.setHeaderEncoding("UTF-8");
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = fileUpload.parseRequest(request);
for (FileItem item : list) {
//如果fileitem中封装的是普通输入项的数据
if (item.isFormField()) {
String name = item.getFieldName();
//解决普通输入项的数据的中文乱码问题
String value = item.getString("UTF-8");
System.out.println("普通数据" + name + " " + value);
} else{
//如果fileitem中封装的是上传文件,得到上传的文件名称,
String fileName = item.getName();
System.out.println(fileName);
InputStream is=item.getInputStream();
//创建一个文件输出流
FileOutputStream fos = new FileOutputStream(existPath+File.separator+fileName);
File file = new File(existPath+File.separator+fileName);
if(!file.exists()){
file.createNewFile();
}
byte buffer[] = new byte[1024];
//判断输入流中的数据是否已经读完的标识
int length = 0;
//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
while((length = is.read(buffer))>0){
fos.write(buffer, 0, length);
}
//关闭输入流
is.close();
//关闭输出流
fos.close();
//删除处理文件上传时生成的临时文件
item.delete();
}
}
三、文件下载
//response.setContentType("text/html;charset=utf-8");
//浏览器不解析,直接下载
response.setContentType("application/octet-stream");
String name=request.getParameter("path");
System.out.println("得到"+name);
System.out.println("改变"+name);
// 当然如果你使用了“全局编码过滤器”,那么这里就不用处理了
String existPath = request.getServletContext().getRealPath("/WEB-INF/upload/"+name);
File file=new File(existPath);
if(!file.exists()){
response.getWriter().write("<h1>内容不存在</h1>");
}
FileInputStream fileInputStream=new FileInputStream(file);
byte b[]=new byte[10240];
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
//得到文件完整名,包括扩展名
name = new String(name.getBytes("GBK"), "ISO-8859-1");
response.addHeader("content-disposition", "attachment;filename=" + name);
int len;
while ((len=fileInputStream.read(b))>0){
outputStream.write(b,0,len);
}
fileInputStream.close();
outputStream.close();