为什么要学文件上传和下载
在目前大数据时代,人们需要知道的东西太多了,俗话说:“好记性不如烂笔头儿”,很多东西都需要使用文件进行记录,而当笔记放在私人笔记本中的时候,文件一多,尤其是对非科班人员来说,既不好管理又不好查找,所以就衍生了上传文件到服务器进行管理的情况。
就像我写博客一样,也是为了记录自己在技术方面的成长,而在自己电脑中其他的文件也很多。如果不停的在自己的电脑上存放文件,即难管理而且会导致电脑的磁盘容量不断减少。
1、需要资源
在基础的学习中可以使用Apache公司提供文件上传架包
一、commons-fileuploader
二、commons-io
以上两个架包在实习文件上传的必备,点击该超链接可以进入下载页面
2、必备知识
multipart/form-data:以二进制分段的形式将数据写入到请求体中
application/x-www-from-urlencoded : 纯表单上传格式,以key:value的形式将数据存在请求体中
使用表单进行文件上传时必须在表单标签中加入enctype属性,且属性值为multipart/form-data,否则需要上传的文件不会写入到请求体
文件上传使用的标签为:<input type="file" name="upLoaderFile">
在上传过程中,由于数据的到达顺序会不一致,所以为了防止错乱,需要创建一个临时的文件,
接收不同时间段到达的文件数据。最后全部的数据都到达的时候组成上传的文件,则该临时文件就可以删除了。
而这个临时文件需要和DiskFileItemFactory绑定。
文件的上传、下载本质上也就是数据流的操作
3、前端页面(jsp页面)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="/UpLoader" method="post" enctype="multipart/form-data">
<input type="file" name="upLoaderFile"><br> //上传文件标签
<input type="submit" value="上传"> //上传提交按钮
</form>
<button><a href="/DownLoader">下载</a></button> //下载文件
</body>
</html>
4、上传Servlet
@WebServlet(urlPatterns = "/UpLoader")
public class UpLoader extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8"); //设置请求头中的内容的字符编码
resp.setContentType("text/html;charset=utf-8"); //设置响应对象中内容的字符编码
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(); //创建一个数据汇总工厂
File file = new File("E:\\temp"); //创建一个临时文件。
if(!file.exists()){ //当文件不存在的时候就新建一个
file.createNewFile();
}
fileItemFactory.setRepository(file); //将临时文件和DiskFileItemFactory绑定。
ServletFileUpload fileUpload = new ServletFileUpload(fileItemFactory); //创建一个FileItem生成器
try {
List<FileItem> fileItems = fileUpload.parseRequest(req); //解析请求,将请求中的参数生成一个个FileItem对象;
for(FileItem item : fileItems){ //遍历请求体中上传的数据
upLoaderFile(item);
}
} catch (FileUploadException e) {
e.printStackTrace();
}
file.delete(); //删除临时文件
resp.getWriter().println("上传成功"); //响应客户端一个成功的提示
}
/**
文件上传处理方法,FileItem为上传的文件对象
*/
private void upLoaderFile(FileItem fileItem){
File file = new File("E:\\" + fileItem.getName()); //在服务端指定的位置放置上传的文件
try{
if(!file.exists()) file.createNewFile(); // 创建上传的文件
OutputStream fileOutputStream = new FileOutputStream(file) ; //得到上传文件的输出流
InputStream inputStream = fileItem.getInputStream(); //得到服务端文件的输入流
byte[] content = new byte[1024];
while((inputStream.read(content)) != -1){ //数据流的输入、输出操作
fileOutputStream.write(content);
}
inputStream.close();
fileOutputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
5、下载Servlet
@WebServlet(urlPatterns = "/DownLoader")
public class DownLoader extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
File file = new File("E:\\timg.jpg"); //需要下载的文件
resp.addHeader("Content-type", "application/octet-stream"); //设置响应的类型为二进制数据
//以附件的形式响应到客户端,filename 只需要文件的名称,下载地址会是浏览器的默认下载地址
resp.addHeader("Content-Disposition","attachment;filename=" + file.getName());
//得到响应对象的输出流
OutputStream outputStream = resp.getOutputStream();
//得到需要下载的文件的输入流
InputStream inputStream = new FileInputStream(file);
byte[] content = new byte[1024];
while((inputStream.read(content)) != -1){ //输入、输出流操作
outputStream.write(content);
}
outputStream.close();
inputStream.close();
}
}
总结
1、使用Apache提供的两个架包进行文件的上传是最基础的方式,有一个弊端就是只能上传单个文件,不支持多文件上传。
2、DiskFileItemFactory 工厂类需要绑定一个临时文件作为数据在网络中传输的汇总区
3、ServletFileUpload 类用于将请求体中的二进制数据封装成FileItem对象,而FileItem对象就是上传到服务端的文件对象
4、熟悉掌握贯穿各种开发模式的数据流知识
5、掌握相应的响应头字段
Content-type:application/octet-stream :将数据封装成二进制数据
Content-Disposition:attachment;filename=”filename" :以附件下载的形式将数据响应给客户端