java web 上传文件详解

目录

纯servlet下使用upload插件上传文件

测试页面

在servlet里

重复文件名问题

多级目录的问题


前言

本篇会讲解在纯servlet下上传文件和框架下上传文件,以及各种上传文件的方式

纯servlet下使用upload插件上传文件

测试页面

我们选择图片提交后

  <form action="UploadServlet" method="post" enctype="multipart/form-data">
  	帐号: <input type="text"  name="username"/>
  	密码: <input type="text" name="password"/>
  	头像: <input type="file"  name="userhead" />
  	<input type="submit"/> 
  </form>

图片是一串数据,并不能用reque.getParameter 来接受

导入upload的jar包

在servlet里

这里为了方便测试,把user放入session中,为了在页面中显示,实际情况中肯定不能这样

因为密码也通过populate给放入了

这个servlet的作用是,把上传到服务器文件,写到另一个地方,这个地方可以是专门存放图片的地方

还有就是要记得释放资源,不然页面显示不了,被jvm占用文件了

还有就是要注意,文件是不能存到tomcat下面的,因为重新发布的时候,文件会被清空

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
	{
		try
		{
			// 创建map集合来接收文件名,有对应的key,通过key找到value会非常快
			Map<String, String> map = new HashMap<String, String>();
			User user = new User();

			// 利用request.getInputStream 获取请求体的全部数据,进行拆分和封装
			//以下3行语句都是固定的
			// 创建文件工厂
			DiskFileItemFactory factory = new DiskFileItemFactory();
			// 创建servlet上传对象
			ServletFileUpload upload = new ServletFileUpload(factory);
			//拆分request,把每份数据变成FileItem
			List<FileItem> list = upload.parseRequest(request);
			
			//遍历FileItem集合
			for (FileItem fileItem : list)
			{
				//是否是普通的数据
				if (fileItem.isFormField())
				{
					//如果是普通数据,那么直接put进去,普通数据就是username和password这些字符串
					map.put(fileItem.getFieldName(), fileItem.getString());
				}
				//如果是文件数据,也就是二进制数据
				else 
				{
					//通过FileItem获取到输入流的对象,通过输入流可以获取到图片
					InputStream is=fileItem.getInputStream();
					
					//创建文件
					File finalFile=new File("C:/Users/1/Desktop/","1.jpg");
					System.out.println("finalFile====="+finalFile.getPath());
					if (!finalFile.exists())
					{
						finalFile.createNewFile();
					}
					
					//将输入流拷贝到输出流中,这个输出流指定了finalFile文件对象
					OutputStream os=new FileOutputStream(finalFile);
					IOUtils.copy(is, os);				
					
					//然后把总的文件名放入map中
					map.put("picture",finalFile.getPath());
					
					//释放资源,必须释放,不然页面显示不了,因为文件被占用了
					IOUtils.closeQuietly(is);
					IOUtils.closeQuietly(os);	
					
				}
			
			}	
			
			//利用BeanUtils把map中的数据填充到user上
			BeanUtils.populate(user, map);
			
			//将user的数据放到数据库中,这里就不写了
			
			//跳转到显示图片页面
			response.sendRedirect(request.getContextPath()+"/show.jsp");
			
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

重复文件名问题

我们上传到同一个文件夹的时候,如果有相同的文件名,原有的文件就会被覆盖,所以需要让每个文件名不同

如果是图片数据,那么就使用工具类重新获取文件名

工具类源码,看的懂就看,看不懂就用

public class UploadUtils {
	/**
	 * 获取随机名称
	 * @param realName 真实名称
	 * @return uuid
	 */
	public static String getUUIDName(String realName){
		//realname  可能是  1.jpg   也可能是  1
		//获取后缀名,防止有的人故意把后缀改了,这样就异常了
		int index = realName.lastIndexOf(".");
		if(index==-1){
			return UUID.randomUUID().toString().replace("-", "").toUpperCase();
		}else{
			return UUID.randomUUID().toString().replace("-", "").toUpperCase()+realName.substring(index);
		}
	}
	
	/**
	 * 获取文件真实名称
	 * @param name
	 * @return
	 */
	public static String getRealName(String name){
		// c:/upload/1.jpg    1.jpg
		//获取最后一个"/"
		int index = name.lastIndexOf("\\");
		return name.substring(index+1);
	}
	
	/**
	 * 获取文件目录
	 * @param name 文件名称
	 * @return 目录
	 */
	public static String getDir(String name){
		int i = name.hashCode();
		String hex = Integer.toHexString(i);
		int j=hex.length();
		for(int k=0;k<8-j;k++){
			hex="0"+hex;
		}
		
		//想要几层目录就写几个hex.charAt
		return "/"+hex.charAt(0)+"/"+hex.charAt(1); 
	}
	
	@SuppressWarnings("unused")
	public static void main(String[] args) {
		//String s="G:\\day17-基础加强\\resource\\1.jpg";
		String s="1.jgp";
		String realName = getRealName(s);
		//System.out.println(realName);
		
		String uuidName = getUUIDName(realName);
		//System.out.println(uuidName);
		
		String dir = getDir(realName);
		System.out.println(dir);
		
		
	}
}

多级目录的问题

上面通过工具类解决了重复文件名

但是还有一个新的文件,那么就是一个文件夹下如果有很多很多图片,那么是导致性能非常非常慢

你打开一个有几十万图片的文件夹,肯定会卡爆,所以应该分很多层目录

猜你喜欢

转载自blog.csdn.net/yzj17025693/article/details/88586779