使用jsp/servlet简单实现文件上传与下载

使用JSP/Servlet简单实现文件上传与下载

    通过学习黑马jsp教学视频,我学会了使用jsp与servlet简单地实现web的文件的上传与下载,首先感谢黑马。好了,下面来简单了解如何通过使用jsp与servlet实现文件上传与下载。
       在写代码之前,我们需要导入两个额外的jar包,一个是common-io-2.2.jar,另一个是commons-fileupload-1.3.1.jar,将这个两个jar 包导入WEB-INF/lib目录里。
       首先,想要在web端即网页上实现文件上传,必须要提供一个选择文件的框,即设置一个<input type="file"/>的元素,光有这个还不行,还需要对<input>元素外的表单form进行设置,将form的enctype属性设置为“multipart/form-data”,即<form action="" method="post" enctype="multipart/form-data">,当然请求方式也必须是post。让我们来简单做一个上传的jsp页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>文件上传</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  
  <body>
    <form action="${pageContext.request.contextPath}/servlet/UploadServlet" method="post" enctype="multipart/form-data">
    	name:<input name="name"/><br/>
    	file1:<input type="file" name="f1"/><br/>
    	
    	<input type="submit" value="上传">
    </form>
  </body>
</html>
       jsp页面做好之后,我们就要写一个UploadServlet,在编写上传servlet时,我们需要考虑到如果上传的文件出现重名的情况,以及上传的文件可能会出现的乱码情况,所以我们需要编码与客户端一致,并且根据文件名的hashcode计算存储目录,避免一个文件夹中的文件过多,当然为了保证服务器的安全,我们将存放文件的目录放在用户直接访问不到的地方,比如在WEB-INF文件夹下创建一个file文件夹。具体做法如下:
public class UploadServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		PrintWriter out = response.getWriter();
		System.out.print(request.getRemoteAddr());
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
		if(!isMultipart){
			throw new RuntimeException("请检查您的表单的enctype属性,确定是multipart/form-data");
		}
		DiskFileItemFactory dfif = new DiskFileItemFactory();
		ServletFileUpload parser = new ServletFileUpload(dfif);
		
		parser.setFileSizeMax(3*1024*1024);//设置单个文件上传的大小
		parser.setSizeMax(6*1024*1024);//多文件上传时总大小限制
		
		List<FileItem> items = null;
		try {
			items = parser.parseRequest(request);
		}catch(FileUploadBase.FileSizeLimitExceededException e) {
			out.write("上传文件超出了3M");
			return;
		}catch(FileUploadBase.SizeLimitExceededException e){
			out.write("总文件超出了6M");
			return;
		}catch (FileUploadException e) {
			e.printStackTrace();
			throw new RuntimeException("解析上传内容失败,请重新试一下");
		}
		
		//处理请求内容
		if(items!=null){
			for(FileItem item:items){
				if(item.isFormField()){
					processFormField(item);
				}else{
					processUploadField(item);
				}
			}
		}
		
		out.write("上传成功!");
	}
	private void processUploadField(FileItem item) {
		try {
			String fileName = item.getName();
			
			
			//用户没有选择上传文件时
			if(fileName!=null&&!fileName.equals("")){
				fileName = UUID.randomUUID().toString()+"_"+FilenameUtils.getName(fileName);
				
				//扩展名
				String extension = FilenameUtils.getExtension(fileName);
				//MIME类型
				String contentType = item.getContentType();
				
				
				
				//分目录存储:日期解决
	//			Date now = new Date();
	//			DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
	//			
	//			String childDirectory  = df.format(now);
				
				
				//按照文件名的hashCode计算存储目录
				String childDirectory = makeChildDirectory(getServletContext().getRealPath("/WEB-INF/files/"),fileName);
				
				String storeDirectoryPath = getServletContext().getRealPath("/WEB-INF/files/"+childDirectory);
				File storeDirectory = new File(storeDirectoryPath);
				if(!storeDirectory.exists()){
					storeDirectory.mkdirs();
				}
				System.out.println(fileName);
				item.write(new File(storeDirectoryPath+File.separator+fileName));//删除临时文件
				
			}
		} catch (Exception e) {
			throw new RuntimeException("上传失败,请重试");
		}
		
	}
	//计算存放的子目录
	private String makeChildDirectory(String realPath, String fileName) {
		int hashCode = fileName.hashCode();
		int dir1 = hashCode&0xf;// 取1~4位
		int dir2 = (hashCode&0xf0)>>4;//取5~8位
		
		String directory = ""+dir1+File.separator+dir2;
		File file = new File(realPath,directory);
		if(!file.exists())
			file.mkdirs();
		
		return directory;
	}
	private void processFormField(FileItem item) {
		String fieldName = item.getFieldName();//字段名
		String fieldValue;
		try {
			fieldValue = item.getString("UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("不支持UTF-8编码");
		}
		System.out.println(fieldName+"="+fieldValue);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}

      至此,上传的任务就基本完成了,有了上传当然也要有下载功能,在下载之前,我们需要将所有已经上传的文件显示在网页上,通过一个servlet与一个jsp页面来显示,servlet代码如下:
public class ShowAllFilesServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String storeDirectory = getServletContext().getRealPath("/WEB-INF/files");
		File root = new File(storeDirectory);
		
		//用Map保存递归的文件名:key:UUID文件名   value:老文件名
		Map<String, String> map = new HashMap<String, String>();
		treeWalk(root,map);
		
		request.setAttribute("map", map);
		request.getRequestDispatcher("/listFiles.jsp").forward(request, response);
	}
	//递归,把文件名放到Map中
	private void treeWalk(File root, Map<String, String> map) {
		if(root.isFile()){
			String fileName = root.getName();//文件名     
			String oldFileName = fileName.substring(fileName.indexOf("_")+1);
			map.put(fileName, oldFileName);
		}else{
			File fs[] = root.listFiles();
			for(File file:fs){
				treeWalk(file, map);
			}
		}
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}
       通过上面的servlet转发到listFiles.jsp页面,listFiles.jsp页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>title</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  
  <body>
    <h1>以下资源可供下载</h1>
    <c:forEach items="${map}" var="me">
    	<c:url value="/servlet/DownloadServlet" var="url">
    		<c:param name="filename" value="${me.key}"></c:param>
    	</c:url>
    	${me.value}  <a href="${url}">下载</a><br/>
    </c:forEach>
  </body>
</html>

      到这里,文件也显示出来了,就需要点击下载进行下载文件了,最后一步,我们再编写一个DownloadServlet:
public class DownloadServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String uuidfilename = request.getParameter("filename");//get方式提交的
		uuidfilename = new String(uuidfilename.getBytes("ISO-8859-1"),"UTF-8");//UUID的文件名
		
		String storeDirectory = getServletContext().getRealPath("/WEB-INF/files");
		//得到存放的子目录
		String childDirecotry = makeChildDirectory(storeDirectory, uuidfilename);
		
		//构建输入流
		InputStream in = new FileInputStream(storeDirectory+File.separator+childDirecotry+File.separator+uuidfilename);
		//下载
		String oldfilename = uuidfilename.substring(uuidfilename.indexOf("_")+1);
		//通知客户端以下载的方式打开
		response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(oldfilename, "UTF-8"));
		
		OutputStream out = response.getOutputStream();
		
		int len = -1;
		byte b[] = new byte[1024];
		while((len=in.read(b))!=-1){
			out.write(b,0,len);
		}
		in.close();
		out.close();
		
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
	//计算存放的子目录
	private String makeChildDirectory(String realPath, String fileName) {
		int hashCode = fileName.hashCode();
		int dir1 = hashCode&0xf;// 取1~4位
		int dir2 = (hashCode&0xf0)>>4;//取5~8位
		
		String directory = ""+dir1+File.separator+dir2;
		File file = new File(realPath,directory);
		if(!file.exists())
			file.mkdirs();
		
		return directory;
	}
}

      文件上传与下载就已经全部完成了。

     
  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值