Java web中上传和下载详解(上)

Java web中上传和下载详解

文件上传:

  1. 先来看一下上传对form表单有什么要求?
    1. 必须是form表单提交。
    2. 表单中的method必须是post,不能是get
    3. 表单中的enctype的属性值必须是:multipart/form-data。当不是multipart的时候,就算<input type="file">提交的效果也和普通的text类型一样。
    4. 表单中项使用file类型
  2. 文件上传对servlet的要求?
    1. 因为表单中上传的不再是字符内容,而是字节内容。就算是上传文本文件也是一样的。所以不能使用request.getParameter(String fieldName)方法。
    2. 那使用什么呢。这个时候可以使用request.getInputStream();方法获取ServletInputStream对象,它是InputStream类的子类,这个对象对应表单的正文部分,关于正文部分下面会介绍。
  3. 关于正文部分介绍。
    1. 这个是有可以使用HTTP抓包工具,我使用的是Firebug。在Firefox进行抓包的。如下图所示:

    2. ServletInput中就包含第二张图片的内容。可以通过以下方法得到
 
   
 
public void doPost(HttpServletRequest request,HttpServletResponse response)throw IOException,ServletException{
    request.setCharacterEncoding("utf-8");
    ServletInputStream in = request.getInputStream;
    String s = IOUtils.toString(in);//Apache的commons组件中的包
    System.out.println(s);//结果如下
}
执行结果如下:
和抓包来的没什么区别
------WebKitFormBoundaryH06xO2noLxVFeenm
Content-Disposition: form-data; name="username"
csdn
------WebKitFormBoundaryH06xO2noLxVFeenm
Content-Disposition: form-data; name="filename"; filename="a.txt"
Content-Type: text/plain
E:\Application\workspace\exam\src\cn\itcast\day20\CountDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileDemo2.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileDemo3.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileDemo4.java
E:\Application\workspace\exam\src\cn\itcast\day20\FileFilterDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\JavaFileList.java
E:\Application\workspace\exam\src\cn\itcast\day20\PrintWriterDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\PropertiesDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\SequenceDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\SequenceInputStreamDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\SequenceVideoDemo.java
E:\Application\workspace\exam\src\cn\itcast\day20\SplitFileDemo.java
------WebKitFormBoundaryH06xO2noLxVFeenm--

上传的任务就是将这些信息解析出来如果是文件部分保存到文件中,不是文件部分该给谁给谁。


4.按照上面的上传文件中ServletInputStream流的格式我自己写了一个,只能上传文本文件的上传方法。(能力有限)
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//得到流对象
		ServletInputStream in = request.getInputStream();
		//将流中的对象写入到一个字符串中。可能使用StringBuffer更好
		int len = 0;
		byte buf[] = new byte[1024];
		String content = "";
		while((len = in.read(buf))!=-1){
			 content = content + new String(buf, 0, len);
		}
		//将内容按行分割
		String[] contents = content.split("\n");
		//将数组转换成数组
		List<String> lists = Arrays.asList(contents);
		//是否包含这个Content-Type: text/plain。也就是文本文件内容的开始了
		System.out.println("执行:"+lists.contains(new String("Content-Type: text/plain")));
		//获取开始和结束位置
		int start = 0;
		int end = 0;
		for (int i=1;i<lists.size();i++) {
			if(lists.get(0).equals(lists.get(i))){
				 end = i;
			}
		}
		
		System.out.println(start+":"+end);
		//将数组按开始位置和结束位置截取
		List<String> fileList = lists.subList(end+4, lists.size()-1);
		//保存的文件
		FileWriter writer = new FileWriter("F:\\a.txt");
		//遍历数组如入文件
		for (String s : fileList) {
			writer.write(s);
			writer.write("\n");
		}
		writer.close();
	}

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


使用Apache的commons组件包实现上传(还是这个强大):



  1. 快速入门(得到的效果和上面的一样):
    1. public void doGet(HttpServletRequest request, HttpServletResponse response)
      			throws ServletException, IOException {
      		//获取解析器工厂
      		DiskFileItemFactory factory = new DiskFileItemFactory();
      		//获得解析器
      		ServletFileUpload fileUpload = new ServletFileUpload(factory);
      		try {
      			//解析request
      			List<FileItem> items = fileUpload.parseRequest(request);
      			//遍历解析得到的FileItem对象
      			for(FileItem item : items){
      				//如果字段名是username
      				if(item.getFieldName().equalsIgnoreCase("username")){
      					//得到提交过来的值
      					System.out.println(item.getString());
      					//如果是这个说明是文件
      				}else if(item.getFieldName().equalsIgnoreCase("fileName")){
      					//得到提交过来的值,如果是文本文件能输出,否则是乱码
      					item.write(new File("F:\\","b.txt"));
      				}
      			}
      			
      		} catch (Exception e) {
      			e.printStackTrace();
      		}
      	}
      
      	public void doPost(HttpServletRequest request, HttpServletResponse response)
      			throws ServletException, IOException {
      		doGet(request, response);
      	}
      


  2. 完全体演示:
    1. 	public void doGet(HttpServletRequest request, HttpServletResponse response)
      			throws ServletException, IOException {
      		//解决中文文件名问题
      		/**
      		 * 也可以是fileUpload.setHeaderEncoding("utf-8");优先级高
      		 */
      		request.setCharacterEncoding("utf-8");
      		
      		//获取解析器工厂,在factory中设置 (1024*20,new File("F://temp");如果文件过大
      		//设置文件超过20kb就缓存,缓存文件是在F盘的temp文件下
      		
      		DiskFileItemFactory factory = new DiskFileItemFactory();
      		//获得解析器
      		ServletFileUpload fileUpload = new ServletFileUpload(factory);
      		//设置上传的全部大小,包括<input type='text'>
      //		fileUpload.setSizeMax(1024*900);
      		
      		//设置上传文件的大小,1024为1kb
      		fileUpload.setFileSizeMax(300*1024);
      		
      //		fileUpload.setHeaderEncoding("utf-8");
      		
      		try {
      			//解析request
      			List<FileItem> items = fileUpload.parseRequest(request);
      			//遍历解析得到的FileItem对象
      			for(FileItem item : items){
      				//如果字段名是username
      				if(item.getFieldName().equalsIgnoreCase("username")){
      					//得到提交过来的值
      					System.out.println(item.getString());
      					//如果是这个说明是文件
      				}else if(item.getFieldName().equalsIgnoreCase("fileName")){
      					//得到文件名
      					String fileName = item.getName();
      					//防止有些浏览器上传文件的时候,上传文件的带盘符的绝对路径。我们只要文件名就行
      					int index = fileName.lastIndexOf("\\");
      					if(index!=-1){
      						fileName = fileName.substring(index+1);
      					}
      					//获取后缀名.假设我只上传静态图片格式的文件,也就是格式是jpg,bmp,png这三种。其他的都不要
      					
      					index = fileName.lastIndexOf(".");
      					//说明没有后缀名
      					if(index==-1){
      						//一般情况是,通过request.setAttribute("msg","您上传的文件没有后缀名,请重新上传");
      						//转发到request.getRequestDispatcher("路径").forward(request, response);
      						//return;
      						
      						//这里我就全输出了
      						System.out.println("上传的文件没有后缀名");
      						return;
      					}
      					
      					String extension = fileName.substring(index+1);
      					//上传文件如果不是以上面三个后缀名结尾,就输出错误信息
      					if (!extension.equalsIgnoreCase("bmp")
      							&& !extension.equalsIgnoreCase("jpg")
      							&& !extension.equalsIgnoreCase("png")) {
      						
      						System.out.println("上传的文件必须是bmp或jpg或png");
      						return;
      					}
      					//上传文件肯定是多个,命名也是一个问题。使用Apache的commons组件的类
      					fileName = getuuid()+"."+extension;
      					
      					
      					//上传的文件放到哪,只能放在WEB-INF下面.如果你下面还要放分目录的话。有很多的算法
      					//有按时间的,用户的,文件名的hash值的等等。看需求
      					//我来按时间,也就是每天一个文件夹
      					String timeStamp = new SimpleDateFormat("yyyy.MM.dd").format(new Date());
      					String savePath = this.getServletContext().getRealPath("/WEB-INF/myupload")+"\\"+timeStamp;
      					File f = new File(savePath);
      					f.mkdirs();
      					item.write(new File(savePath,fileName));
      					item.delete();//删除临时文件
      }}} catch (Exception e) {if(e instanceof FileUploadBase.FileSizeLimitExceededException){System.out.println("上传文件不能大于300kb");return;}else{e.printStackTrace();}}}public static String getuuid() {return UUID.randomUUID().toString().replace("-", "");}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}
      
      
      
      
    2. 如果还要判断上传文件的宽度和高度。只需在后面加上:
      					File f = new File(savePath);
      					f.mkdirs();
      					File saveFile = new File(savePath,fileName);
      					item.write(saveFile);
      					item.delete();//删除临时文件
      					
      					ImageIcon icon = new ImageIcon(saveFile.getAbsolutePath());
      					Image image = icon.getImage();
      					image.getHeight(null);//得到图片的高
      					image.getWidth(null);//得到文件的宽
      					
      					//如果不满足条件
      					saveFile.delete();

其他类型的文件也就类似了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值