java 文件的上传和下载

一.文件的上传

<form action="/upload" method="post" enctype="multipart/form-data" ><br>
		姓名:<input  type="text" name="username" ><br>
		年龄:<input  type="text" name="age" ><br>
		文件:<input  type="file" name="headImage1" ><br>
		文件:<input  type="file" name="headImage2" ><br>
		<input type="submit" value="提交" >
</form>

@WebServlet("/upload")
public class uploadServlet  extends HttpServlet{
	@Override
	protected void service(HttpServletRequest request,
               HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		Map<String,Object> map = new HashMap<>();
		try {
			FileUploadUtils.upload(request,map);
			System.out.println(map);
		} catch (LoginException e) {
			request.setAttribute("errorMeg", e.getMessage());
			request.getRequestDispatcher("/upload/upload.jsp").
                      forward(request, response);
			System.out.println(e.getMessage());
		}
	 
	}
}



public class FileUploadUtils {
	// 文件的上传操作
	public static void upload(HttpServletRequest request,
			Map<String, Object> map) throws UnsupportedEncodingException {
		/*
		 * 1 得到上传文件保存的目录,将文件存放在WEB-INF目录下,
		 * 不允许外界直接访问,保证上传文件的安全 通过相对路径获得绝对路径 带盘符
		 */
		String savePath = request.getServletContext().getRealPath("WEB-INF/upload");
		// 2 设置上传文件时,如果文件过多,保存的临时目录
		String tempPath = request.getServletContext().getRealPath("WEB-INF/temp");
		File tempFile = new File(tempPath);
		
		if (!tempFile.exists()) {
			// 创建临时文件夹
			tempFile.mkdirs();
		}
		// 3 解析请求
		// 验证请求是否满足要求(post和enctype是否为multipart/开头)
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
		// 如果不满足条件,就立即结束对该请求的处理
		if (!isMultipart) {
			return;
		}
		try {
			// FileItem实际上就是表单中的每一个表单元素的封装
			// <input type="text" name="username" ><br>

			// 3.1 创建FileItem的工厂类
			DiskFileItemFactory factory = new DiskFileItemFactory();
			/* 3.2 设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,
			                就会生成一个临时文件存放到指定的临时目录当中。 */
			factory.setSizeThreshold(1024 * 500);
			// 3.3 设置临时目录
			factory.setRepository(tempFile);

			// 3.4 创建一个文件上传处理器(装饰者模式)
			ServletFileUpload upload = new ServletFileUpload(factory);
			// 3.5 监听文件上传的进度
			upload.setProgressListener(new ProgressListener() {
				@Override
				public void update(long pBytesRead, long pContentLength, int pItems) {
					System.out.println("当前的文件大小为:" + pContentLength + 
							",当前文件已处理:" + pBytesRead);
				}
			});
			// 3.6 解决上传文件过程中文件名出现的乱码问题
			upload.setHeaderEncoding("UTF-8");
			// 3.7 设置单个文件上传的大小5M
			upload.setFileSizeMax(1024 * 5000);
			// 3.8 设置整个请求中上传文件和数据的大小 10M
			upload.setSizeMax(1024 * 10000);
			// 解析请求
			List<FileItem> items = upload.parseRequest(request);
			for (FileItem fileItem : items) {
				// 3.9 判断控件是否是普通控件
				if (fileItem.isFormField()) {
					map.put(fileItem.getFieldName(), fileItem.getString("UTF-8"));
				} else {
					String fileName = null;
					if (null == fileItem.getName() || 
                           "".equals(fileItem.getName().trim())) {
						continue;
					} else {
						/* 不同的浏览器提交的文件名是不一样的
                           ,有些浏览器提交上来的文件名是带有路径的,如: c:\a\2.png */
						if (fileItem.getName().contains("\\")) {
							fileName = fileItem.getName().substring(
									fileItem.getName().lastIndexOf("\\") + 1);
							// 得到文件的扩展名
							// String fileExtName =
							// FilenameUtils.getExtension(fileItem.getName());
							String fileExtName = fileItem.getName().substring
									(fileItem.getName().lastIndexOf(".") + 1);
						} else {
							fileName = fileItem.getName();
						}
					}

					// 3.10 保存文件的文件名 避免文件名重复 用工具类获得文件的拓展名
					String saveFileName = UUID.randomUUID().toString() + "_" + fileName;
					System.out.println(fileItem.isInMemory());
					// 3.11 上传文件的约束
					String contentType = fileItem.getContentType();
					if (!contentType.startsWith("image/")) {
						throw new LoginException("亲,您的文件格式不正确!");
					}
					// 3.12 保存文件的文件目录
					// 为防止一个目录下面出现太多文件,要使用hash算法打散存储
					/* 得到文件名的hashCode的值,得到的就是filename这个
                        字符串对象在内存中的地址  */
					int hashCode = saveFileName.hashCode();
					int dir1 = hashCode & 0xf; // 0--15
					int dir2 = (hashCode & 0xf0) >> 4; // 0-15
					// 构建一个新的保存目录     // upload\1\2
					String realSavePath = savePath + "\\" + dir1 + "\\" + dir2; 
					// File 可以是目录结构
					File saveFileDir = new File(realSavePath);
					// 目录不存在就创建目录
					if (!saveFileDir.exists()) {
						saveFileDir.mkdirs();
					}
					System.out.println("通过相对路径获取绝对路径:" + realSavePath);
					fileItem.write(new File(realSavePath, saveFileName));
					map.put(fileItem.getFieldName(), saveFileName);
				}
			}
			// 自定义异常,抛出去在Servlet中统一处理,返回给前端
		} catch (SizeLimitExceededException e) {
			throw new LoginException("多个文件上传大小不超过700kb", e);
		} catch (FileSizeLimitExceededException e) {
			throw new LoginException("上传文件大小不超过500KB", e);
		} catch (LoginException e1) {
			throw e1;
		} catch (Exception e) {
			throw new LoginException("文件上传失败!", e);
		}

	}
}

二.文件的下载

    1.得到所有上传文件夹下面的文件

@WebServlet(value="/listFile")
public class ListFileServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		/******要有一个页面列出上传文件目录下的所有文件,
           当用户点击文件下载超链接时就进行下载操作**/
		// 1 获取上传文件的目录
		String uploadFilePath = request.getServletContext()
                .getRealPath("/WEB-INF/upload");
		// 2 获得将要存放下载文件的文件名
		Map<String,Object> fileNameMap = new HashMap<>();
		// 3 遍历获得所有指定目录下面的文件
		File fileOrFolder = new File(uploadFilePath);
		listFile( fileOrFolder,  fileNameMap);
		// 4 将文件名发送到前端进行显示
		request.setAttribute("fileNameMap", fileNameMap);
		// 5 请求转发
		request.getRequestDispatcher("/download.jsp").forward(request, response);
	}
	 public void listFile(File file,Map<String, Object> fileNameMap){
			// file是目录
			if(!file.isFile()){
				File[] listFiles = file.listFiles();
				for (File f : listFiles) {
					// 递归遍历
					listFile(f,fileNameMap);
				}
			}else{
				/*处理文件名,上传后的文件是以uuid_文件名的形
				 * 式去重新命名的,去除文件名的uuid_部分*/
				String realName = file.getName().substring(
                        file.getName().indexOf("_")+1);
				// file.getName() 得到是带有uuid的文件名,是唯一的,可以作为key
				fileNameMap.put(file.getName(), realName);
			}
		 }
}

2.前端页面显示要下载的文件

	<h1>资源下载</h1>
	<!--遍历map集合  -->
	<c:forEach items="${fileNameMap}" var="fnm"  >
		<c:url value="/download" var="downloadurl" >
			<c:param name="fileName" value="${fnm.key }" ></c:param>
		</c:url>
		${fnm.key }<a href="${downloadurl}" >下载</a><br>
	</c:forEach>

3.对文件进行下载

@WebServlet("/download")
public class DownLoadServlet extends HttpServlet {
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=utf-8");
		// 设置响应数据的MIME类型
		response.setContentType("application/x-msdownload");
		// 1 获取前端传过来的文件名称
		String filename = request.getParameter("fileName");
		String fileName = new String(filename.getBytes("ISO-8859-1"),"UTF-8");
		// 2 获得文件上传的子目录 WEB-INF/upload
		String fileSaveRootPath = this.getServletContext().
             getRealPath("/WEB-INF/upload");
		// 3 通过文件名找出文件所在的目录
		int hashCode = fileName.hashCode();
		int dir1 = hashCode & 0xf; // 0--15
		int dir2 = (hashCode & 0xf0) >> 4; // 0-15
		// 4 得到文件所在的目录
		String realSavePath = fileSaveRootPath + "\\" + dir1 + "\\" + dir2; // upload\1\2
		File saveFileDir = new File(realSavePath);
		if (!saveFileDir.exists()) {
			saveFileDir.mkdirs();
		}
		// 5 得到要下载的文件  绝对路径+文件名
		File downloadFile = new File(realSavePath,fileName);
		if(!downloadFile.exists()){
			 request.setAttribute("message", "您要下载的资源已被删除!!");
			 request.getRequestDispatcher("/error.jsp").forward(request, response);
			  return;
		}
		
		// 6 判断浏览器是否是IE浏览器
		String userAgent = request.getHeader("User-Agent");
		// 7 解决下载保存文件乱码问题
		 //处理文件名
		String realname = fileName.substring(fileName.indexOf("_")+1);
		if(userAgent.contains("MSIE")){
			// IE 设置响应抱头
			realname =  URLEncoder.encode(realname, "UTF-8");
			response.setHeader("Content-disposition", "attachment;filename="+ realname);
		}else{
			// FireFox
			realname = new String(realname.getBytes("UTF-8"),"ISO-8859-1");
			response.setHeader("Content-disposition", "attachment;filename="+realname );
			System.out.println(realname);
		}
		ServletOutputStream outStream = response.getOutputStream();
		// 8 将文件复制到输出流中,响应给浏览器
		Files.copy(Paths.get(downloadFile.getAbsolutePath()), outStream);
	}
}

猜你喜欢

转载自blog.csdn.net/m0_38068812/article/details/82556846