一、文件上传
1.使用的组件
使用DiskFileItemFactory、ServletFileUpload、FileItem三个组件实现。依赖的jar包为commons-fileupload-1.4.jar、commons-io-2.7.jar,下载地址:
https://download.csdn.net/download/Albert201605/26346276
——调用方法的说明
DiskFileItemFactory——解析器工厂,用于创建对请求内容的解析器
(1) public void setSizeThreshold(int sizeThreshold)
设置内存缓冲区的大小,默认值为10K。当上传的文件大于缓冲区的大小时,fileupload组件将使用临时文件缓存上传的文件。
(2) public void setRepository(Java.io.File repository)
指定临时文件目录,默认值为System.getProperty(“java.io.tmpdir”).
(3) public DiskFileItemFactory(int sizeThreshold,java.io.File repository)
构造函数,同时赋以缓冲区大小和临时文件目录
ServletFileUpload——解析器,用以解析请求体的内容
(1)boolean isMultipartContent(HttpServletRequest request)
判断上传表单是否为multipart/form-data类型
(2) List parseRequest(HttpServletRequest request)
解析request对象,并把表单中的每一个输入项封装成一个FileItem 对象,返回一个保存了所有FileItem的List集合。
(3) setFileSizeMax(long fileSizeMax)
设置上传文件的最大值(单个文件),用于设置单个上传文件的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。
(4) setSizeMax(long sizeMax) :
设置整个请求消息实体内容(整个表单数据)的最大尺寸限制,以防止客户端恶意上传超大文件来浪费服务器端的存储空间。其参数是以字节为单位的long型数字。
(5) setHeaderEncoding(java.lang.String encoding)
设置编码格式。在文件上传请求的消息体中,除了普通表单域的值是文本内容以外,文件上传字段中的文件路径名也是文本,在内存中保存的是它们的某种字符集编码的字节数组,Apache文件上传组件在读取这些内容时,必须指定所采用的字符集编码方式,才能将它们转换成正确的字符文本返回。
FileItem——条目对象,用以保存封装的表单字段
(1) boolean isFormField()
isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果是普通表单字段返回true,否则返回false。
(2) String getName()
用于获得文件上传字段中的文件名。注意IE或FireFox中获取的值是不一样的,IE中获取的是绝对路径,FireFox中获取的仅是文件名。
(3) String getFieldName()
用于返回表单标签的name名。
(4) void write(File file)
用于将FileItem对象中保存的主体内容写入到某个指定的文件中。如果FileItem对象中的主体内容是保存在某个临时文件中的,在该方法顺利完成后,临时文件有可能会被清除。使用该方法也可将普通表单字段内容写入到一个文件中,但它的主要用途仍是将上传的文件内容保存至本地文件系统中。
(5) String getString()
用于将FileItem对象中保存的数据流内容以一个字符串返回,它有两个重载的定义形式:
public Java.lang.String getString();
public java.lang.String getString(java.lang.String encoding) throws java.io.UnsupportedEncodingException
前者使用缺省的字符集编码将主体内容转换成字符串,后者使用参数指定了字符集编码将主体内容转换成字符串。如果在读取普通表单字段元素的内容时出现了中文乱码现象,则可调用第二个getString方法,指定正确的字符集编码格式。
(6) void delete()
delete方法用于清空FileItem对象中存放的主体内容,如果主体内容被保存在了临时文件中,那么delete方法将删除该临时文件。值得注意的是,尽管当FileItem对象被垃圾收集器收集时会自动地清除临时文件,但及时调用delete方法可以更早地清除冗余的临时文件,有效释放系统的存储资源。
2.实现步骤
s1.创建解析器工厂;
s2.创建Servlet解析器;
s3.解析请求,将表单的每个输入项封装为一个FileItem对象;
s4.逐个处理item条目。对文件字段:创建文件 -> item内容写入。
**注:**在前端JSP页面中,须使用form表单,同时 (1)method须设置为post;
(2)须设置enctype=”multipart/form-data”,作用是将表单数据用以标签为单元、用分隔符分开的形式构造请求体。
二、文件下载
通过输入/输出流完成。
实现步骤:
s1.将指定的文件生成输入流;
s2.获取响应输出流;
s3.将流对拷。
三、实现Demo
IDEA开发,一个jsp页面,一个上传Servlet,一个下载Servlet。
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Demo of File Upload and Download</title>
</head>
<body>
<form action="/UploadServlet" method="post" enctype="multipart/form-data">
<input type="text" name="my_comment" value="备注信息"/>
<input type="file" name="my_file"/>
<input type="submit" value="上传"/>
</form>
<%
String download_file_name = "你好123abcdef.txt";
%>
<a href="/DownloadServlet?filename=<%=download_file_name%>">下载文件</a>
</body>
</html>
UploadServlet.java
@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
/** 1.创建解析器工厂 */
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置工厂内存缓存区大小,若未设定,则默认为10k
factory.setSizeThreshold(1024*1024); //1M,参数是以字节为单位的int值。
//设置工厂的临时文件目录
File temp_file = new File("D:\\TempFolder");
if (!temp_file.exists()){
temp_file.mkdirs();
}
factory.setRepository(temp_file);
/** 2.创建Servlet解析器 */
ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
//设置上传数据的规模限制
servletFileUpload.setSizeMax(1024*1024); //全体数据的最大尺寸限制(参数是以字节为单位的long值,这里是1M)
servletFileUpload.setFileSizeMax(1024*1024); //单个文件的最大尺寸限制(参数是以字节为单位的long值,这里是1M)
//设置字符编码格式
servletFileUpload.setHeaderEncoding("UTF-8");
try {
/** 3.解析请求,将表单的每个输入项封装为一个FileItem对象 */
List<FileItem> itemList = servletFileUpload.parseRequest(request);
/** 4.逐个条目处理*/
for (FileItem item : itemList) {
if (item.isFormField()){ //普通字段
String field_name = item.getFieldName(); //获得字段的name名
String field_value = item.getString("UTF-8"); //获得字段的值
System.out.println("field_name:"+field_name);
System.out.println("field_value:"+field_value);
}else { //文件字段
String field_name = item.getFieldName(); //获得字段的name名
String file_name = item.getName(); //获得上传文件的文件名称(对IE和FireFox,获取的值不同,对IE获取的是绝对路径,对FireFox获取的是文件名)
System.out.println("上传的文件名称:"+file_name);
//将item的内容存至磁盘文件
String upload_path = "D:\\myUploadedFile\\" + file_name;
File file = new File(upload_path); //定义文件对象
if (!file.exists()){ //若文件不存在,则创建
file.getParentFile().mkdirs();
file.createNewFile();
}
//方式一:以IO流的形式写入
InputStream inputStream = item.getInputStream(); //以输入流的形式获取item内容
FileOutputStream fileOutputStream = new FileOutputStream(file); //定义文件输出流,指定输出至文件对象
//将流对拷
byte[] bytes = new byte[1024]; //每次读取一个字节
int len;
while ((len=inputStream.read(bytes))>0) //读取输入流,写入输出流
fileOutputStream.write(bytes,0,len);
/*
//方式二:将item主体内容直接写入
//注:如果FileItem对象中的主体内容是保存在某个临时文件中,该方法顺利完成后,临时文件有可能会被清除
item.write(file);
*/
inputStream.close();
fileOutputStream.close();
item.delete(); //释放item占用的存储资源
//向前端发出提示,重定向回主页面
PrintWriter printWriter=response.getWriter();
printWriter.print("<script>alert('上传成功!');window.location='"+request.getContextPath()+"/';</script>");
}
}
}catch (Exception e){
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
DownloadServlet.java
@WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String filename = request.getParameter("filename"); //获取前端传来的参数
response.setContentType("text/html;charset=utf-8"); //通知客户端内容类型
response.addHeader("Content-Type","application/octet-stream");
response.addHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename, "UTF-8")); //通知浏览器以下载的方式打开,并对文件名进行编码
//1.将指定的文件生成输入流
String download_path = "D:\\myUploadedFile\\" + filename;
File file = new File(download_path); //定义文件对象
InputStream inputStream = new FileInputStream(file); //将文件对象生成为输入流
//2.获取响应输出流
OutputStream outputStream = response.getOutputStream();
//3.将流对拷
byte[] bytes = new byte[1024]; //每次读取一个字节
int len;
while ((len=inputStream.read(bytes))>0) //读取输入流,写入输出流
outputStream.write(bytes,0,len);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
Demo工程文件打包下载:
https://download.csdn.net/download/Albert201605/26347671
End.
参考
- https://blog.csdn.net/u014785687/article/details/73863964
- https://www.cnblogs.com/w-wfy/p/6239330.html