文件上传、下载

需求:将文件上传到服务器,在服务器上保存,并提供下载。

相当于实现了网络硬盘的功能。

 

上传文件

思路:

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");
	}



你可能感兴趣的:(javaee)