需求:将文件上传到服务器,在服务器上保存,并提供下载。
相当于实现了网络硬盘的功能。
上传文件
思路:
1,首先通过表单的<input type=”file” name=”uploadFileName”>实现从浏览器选择文件的功能,
2,表单提交时,会将文件提交到服务器,但这时只是提交了这个文件的文件名,并没有提交文件的内容,如何提交文件的内容呢?要在表单中设置enctype属性:
<formaction="${pageContext.request.contextPath }/servlet/UploadServlet"method="post" enctype="multipart/form-data">
这样服务器就可以获取上传的文件的内容了。
3,表单提交到一个servlet,这个servlet处理上传文件的内容,负责读取上传的文件,并将文件保存在服务器上,
4,文件上传过程中用到了两个第三方的jar包,分别是commons-fileupload.jar和commons-io.jar,其中最核心的类是ServletFileUpload。
5,整个执行流程为:先获取工厂类DiskFileItemFactory,通过工厂类实例可以设大小和临时文件保存地址。然后创建核心类ServletFileUpload,以工厂类实例为参数创建其对象,再通过parseRequest方法解析请求消息,通过getName方法获取上传的文件名称,为了防止提交的文件在服务器重复,可以使用在头部添加UUID唯一随机码解决。通过getInputStream方法可以获取从浏览器读取数据的流对象,然后再创建输出流对象,指定输出地址,通过频繁的读写操作,完成保存动作。
6,上传完毕,将页面转发到下载页面,显示可供下载的信息。
7,下载页面的超链接通过在链接尾部追加文件名来确定下载哪个文件。
下载文件
8,下载的超链接链接到一个servlet,servlet通过文件名获取服务器的资源,并解决乱码问题。
9,如果直接通过流写出到浏览器,那么浏览器会直接将文件解析在浏览器中显示,并不提供下载功能。要想下载文件,其核心是要在servlet的response对象中设置响应头信息:
response.setHeader("content-disposition", "attachment;filename=" + fileName);
10,设置以后,再通过流输出到浏览器时,浏览器就会通过下载的方式与用户交互了。
核心代码:
上传:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//判断是否支持上传。
if(!ServletFileUpload.isMultipartContent(request)) {
throw new RuntimeException("请填写enctype");
}
//创建工厂。
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
fileItemFactory.setSizeThreshold(1024*1024*2);
fileItemFactory.setRepository(new File(this.getServletContext().getRealPath("/WEB-INF/temp")));
//创建核心类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
//设置上传文件名的编码。
servletFileUpload.setHeaderEncoding("utf-8");
//解析request上传的内容。
try {
List<FileItem> allFileItem = servletFileUpload.parseRequest(request);
//遍历
for(FileItem fileItem : allFileItem) {
//检查普通字段.
if(fileItem.isFormField()) {
//是普通字段.
String fieldName = fileItem.getFieldName();//获取名称。
String value = fileItem.getString("utf-8");//获取内容,并设置编码
System.out.println(fieldName+":"+value);
} else {
//上传字段。
//上传文件名称
String fileName = fileItem.getName();
//截取文件名
fileName.substring(fileName.lastIndexOf(File.separator)+1);
//用UUID解决上传的文件名重复的问题。
fileName = UUIDUtils.getUUID()+"_"+fileName;
//文件上传
InputStream is = fileItem.getInputStream();
//保存
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
//文件输出流。
OutputStream out = new FileOutputStream(new File(uploadPath,fileName));
int len = -1;
byte[] buffer = new byte[1024];
while((len = is.read(buffer))!= -1) {
out.write(buffer, 0, len);
}
out.close();
is.close();
//删除临时文件,必须先关闭输入输出流。
fileItem.delete();
}
}
} catch (FileUploadException e) {
throw new RuntimeException(e.getMessage(),e);
}
//上传完成,重定向到下载页面查看自己的下载资源
response.sendRedirect(request.getContextPath()+"/servlet/DownloadServlet");
}
下载:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取要下载的文件名
String fileName = request.getParameter("fileName");
//解决中文乱码。
fileName = new String(fileName.getBytes("iso-8859-1"),"utf-8");
//获得在服务器端的实际路径,对应的资源流
InputStream filePathIs = this.getServletContext().getResourceAsStream("/WEB-INF/upload/" + fileName);
//3 通知浏览器下载
// * 截取前缀
fileName = fileName.substring(33);
// * 处理中文乱码
fileName = new String(fileName.getBytes("GBK"),"ISO-8859-1");
// * 设置头
response.setHeader("content-disposition", "attachment;filename=" + fileName);
OutputStream out = response.getOutputStream();
int len = -1;
byte[] buffer = new byte[1024];
while((len = filePathIs.read(buffer))!= -1) {
out.write(buffer, 0, len);
}
request.getRequestDispatcher(request.getContextPath()+"/servlet/DownloadServlet");
}