java实现文件上传

1.文件上传概述

就是把客户端(浏览器)的文件保存一份到服务器 说白了就是文件的拷贝

2.文件上传要求

2.1浏览器端要求(通用浏览器的要求)

  • 表单提交方式 post
  • 提供文件上传框(组件) input type="file"
  • 表单的entype属性必须为 multipart/form-data(没有这个属性值的话, 文件的内容是提交不过去的)

2.2服务器端要求

要使用request.getInputStream()来获取数据. 

注意:

若表单使用了 multipart/form-data ,使用原生request.getParameter()去获取参数的时候都为null

3.常见的文件上传框架

commons-fileupload : 偏底层   

struts2(底层:commons-fileupload)   

SpringMVC

serlvet3.0 

...

4.这里介绍的是commons-fileupload的使用

commons-fileupload是apache出品的一款专门处理文件上传的工具类 

使用步骤:

  1. 导入jar包

  2. 创建磁盘文件项工厂
    DiskFileItemFactory factory=new DiskFileItemFactory();

  3. 创建核心上传对象
    ServletFileUpload upload=new ServletFileUpload(factory);

  4. 解析请求,获取所有的上传组件 List
    List list=upload.parseRequest(request);

  5. 遍历list 获取每一个上传项

FileItem的API:

getFiledName():获取标签里面name属性的值

isFormFiled():判断是否是普通上传组件;

	true:普通上传组件

	false:文件上传组件
  • 普通上传组件, 不是File, 目的获得值
    getString("utf-8"):获取(普通上传组件)用户输入的内容
  • 文件上传组件 是File , 目的: 获得文件名, 获得文件的内容
    getName():获取文件名称
    getInputStream():获取文件的流(文件内容)
    delete():删除文件上传时候产生的临时文件

Eg:

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      try {
		//创建磁盘文件项工厂
		DiskFileItemFactory factory = new DiskFileItemFactory();
		//创建核心上传对象
		ServletFileUpload fileUpload = new ServletFileUpload(factory);
		//获得所有的上传组件
		List<FileItem> list = fileUpload.parseRequest(request);
		for (FileItem fileItem : list) {	
			//判断是否是文件上传
			if(fileItem.isFormField()){
				//普通上传组件
             	 //获得标签的name属性值
				String key = fileItem.getFieldName();
				//获得普通上传组件的内容.括号中编码避免中文乱码
				String value = fileItem.getString("utf-8");		
			}else{
				//文件上传组件
				//获得文件上传组件的输入流
				InputStream is = fileItem.getInputStream();
				//创建文件输出流
				OutputStream os= new FileOutputStream("G:/1.txt");
				//开始复制
				IOUtils.copy(is, os);	
              //最后关闭流
				os.close();
                is.close();
			}
		}	
	} catch (Exception e) {
		e.printStackTrace();
	}
}

5上传注意问题

  1. 文件重名问题 后面的会把前面的覆盖掉
    给文件取一个随机名称, uuid方式 或者 毫秒值+三个随机数

  2. 文件名称问题 目的是获得文件真实名字,不带盘符的

    如果是低版本IE:文件名带盘符E:/data/Desktop/a.txt
    其它的火狐,谷歌是文件本来的名字: a.txt 
    
  3. 常见的目录分离
    按用户划分 适合用户量不大的项目 < 1w
    按时间划分 2018/03/21/17/07
    按数量划分 eg:以2000个为单位
    随机划分 写算法

附:解决文件上传问题的小工具.

import java.util.Random;
import java.util.UUID;
public class UploadUtils {
/**
 * 获取文件真实名称
 * 由于浏览器的不同获取的名称可能为:E:\data\Desktop\a.txt
 * 最终获取的为  1.jpg
 * @param name 上传上来的文件名称
 * @return	真实名称
 */
public static String getRealName(String name){
	//获取最后一个"/"
	int index = name.lastIndexOf("\\");
	return name.substring(index+1);
}
/**
 * 获取随机名称
 * @param realName 真实名称
 * @return uuid 随机名称
 */
public static String getUUIDName(String realName){
	//realname  eg: a.jpg  ---> UUID.jpg;    a --- > UUID
	//获取后缀名
	int index = realName.lastIndexOf(".");
	if(index==-1){
		return UUID.randomUUID().toString().replace("-", "").toUpperCase();
	}else{
		return UUID.randomUUID().toString().replace("-", 			                         		"").toUpperCase()+realName.substring(index);
		}
	}
/**
 * 获取文件目录,可以获取256个随机目录
 * @return 随机目录
 */
public static String getDir(){//  
	String s="0123456789ABCDEF";
	Random r = new Random();
	return "/"+s.charAt(r.nextInt(16))+"/"+s.charAt(r.nextInt(16));
	}
}

前端页面示例:

<%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>Insert title here</title>
	</head>
	<body>
		<form action="${pageContext.request.contextPath }/demo01" method="post" 	enctype="multipart/form-data">
			用户名:<input type="text" name="name"/> <br/>
			文件:<input type="file" name="file"/> <br/>
			<input type="submit" />
		</form>
	</body>
</html>

posted on 2018-03-21 21:14  无冥  阅读(188)  评论(0编辑  收藏  举报