java文件上传总结

最近公司项目用到文件上传,总结一下

第一种 传统表单上传比较简单,网上也有好多文章介绍,推荐一篇:表单方式文件上传和下载

再此只提醒两点:

一,form表单中要加入enctype="multipart/form-data" method="post"

POST上传文件

最早的HTTP POST是不支持文件上传的,在1995年,ietf出台了rfc1867,也就是《RFC 1867 -Form-based File Upload in HTML》,用以支持文件上传。所以Content-Type的类型扩充了multipart/form-data用以支持向服务器发送二进制数据。因此发送post请求时候,表单<form>属性enctype共有二个值可选,这个属性管理的是表单的MIME编码:

 ①application/x-www-form-urlencoded(默认值)
 ②multipart/form-data

二, 如果使用ssm框架时,不要有如下配置,不然会报错:fileupload插件调用upload.parseRequest(request)解析得到空值

<bean id="multipartResolver"
  class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
  <!-- 设置上传文件大小的参数 ,当前为100M -->
  <property name="maxUploadSize" value="104857600" />
 </bean>

表单提交提醒很不方便,

第二种 写原生的Ajax,用XMLHttpRequest 和FormData对象

前台用的是jsp

<%@ page language="java" contentType="text/html; charset=GBK"
    pageEncoding="GBK"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GBK">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>上海电信</title>
<jsp:include page="main.jsp"></jsp:include>
<script type="text/javascript">
function deviceTotal_check(){
	var result=true;
	var deviceTotal = $("#deviceTotal").val().trim();
	var reg=/^[0-9]*$/;
	if (deviceTotal == null || deviceTotal.length == 0){
		result = false;
	}
	if(!reg.test(deviceTotal)){
		result = false;
	}
	return result;
}
function enterFile_check(){
	var result=true;
	var enterFile = document.getElementById("enterFile").value;
	if (enterFile == null || enterFile.length == 0){
		result = false;
	}
	return result;
}
function deviceFile_check(){
	var result=true;
	var deviceFile = document.getElementById("deviceFile").value;
	if (deviceFile == null || deviceFile.length == 0){
		result = false;
	}
	return result;
}
//XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
function UpladFile() {
	if(!enterFile_check()){
		alert("企业附件不能为空!");
		return false;
	}
	if(!deviceFile_check()){
		alert("分机附件不能为空!");
		return false;
	}
	if(!deviceTotal_check()){
		alert("分机总数不合法!");
		return false;
	}
    var fileObj1 = document.getElementById("enterFile").files[0]; // js 获取文件对象
    var fileObj2 = document.getElementById("deviceFile").files[0]; // js 获取文件对象
    var fileObj3 = $("#deviceTotal").val(); // js 获取文件对象
    var FileController = "${pageContext.request.contextPath}/mvc/dataAcquisition/uploads";                    // 接收上传文件的后台地址 
    // FormData 对象
    var form = new FormData();
    //form.append("author", "hooyes");                        // 可以增加表单数据

    form.append("enterFile", fileObj1);                           // 文件对象
    form.append("deviceFile", fileObj2);                           // 文件对象
    form.append("deviceTotal", fileObj3);                           // 文件对象
    
    xhr.onreadystatechange = callBack;
    xhr.open("post", FileController, true);
    xhr.upload.addEventListener("progress", progressFunction, false);
    xhr.send(form);
}

function progressFunction(evt) {
    var progressBar = document.getElementById("progressBar");
    var percentageDiv = document.getElementById("percentage");
    if (evt.lengthComputable) {
    	//$("#alertModal").modal({show:true});
        progressBar.max = evt.total;
        progressBar.value = evt.loaded;
        percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
    }
    if(evt.total==evt.loaded){
    	//$("#alertModal").modal('hide');
    	
    }
}  
function callBack(){
	if(xhr.readyState==4){
		if(xhr.status==200){
			var msg=$("#message").val();
			clearInput();
	    	alert("操作完成!"+msg)
			//xhr.responseText;
		}
	}
}
function clearInput(){
	$("#enterFile").val("");
	$("#deviceFile").val("");
	$("#deviceTotal").val("");
}
</script>

<style>
	body {
	   font-family: "Times New Roman", "Microsoft YaHei", "微软雅黑", STXihei, "华文细黑", serif;
	   background-color: #F0F0F2;
	}
</style>
</head>
<body>
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true" style="width:500px;margin-top:20px; margin-left: auto; margin-right: auto;">
  
  <div class="panel panel-default">
    <div class="panel-heading" role="tab" id="headingOne" style="background-color: #404f64;color: #ffffff;">
      <h4 class="panel-title">
        <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
         <b> 数据采集  </b>
        </a>
      </h4>
    </div>
    <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="headingOne">
      <div class="panel-body">
      <input type="hidden" id="message" value="${msg }">
            <table align="center" width="100%" class="form-inline">
               <tr height="60px;">
                  <td align="right"><label >企业附件:</label></td>
				  <td>
				    <input class="form-control" style="width:230px;" type="file" id="enterFile" name="enterFile"/>
                  </td>
               </tr>
               <tr height="60px;">
                  <td align="right"><label >分机附件:</label></td>
				  <td>
				   <input class="form-control" style="width:230px;" type="file" id="deviceFile" name="deviceFile"/>
                  </td>
               </tr>
               <tr height="60px;">
                  <td align="right"><label >分机总数:</label></td>
				  <td>    
					 <input name="deviceTotal" id="deviceTotal" class="form-control" style="width: 230px;height: 35px;"/>
                  </td>
               </tr>
               <tr>
               	  <td style="padding-left:80px;" colspan="2">
               	  	  <button type="button" onclick="UpladFile()" class="btn mybtn" style="width: 115px;height: 30px;background-color: #404f64;color: #ffffff">提交</button>
					  <button type="button" onclick="clearInput()" class="btn mybtn" style="width: 115px;height: 30px;background-color: #ff634d;color: #ffffff">清空</button>
                  </td>
               </tr>
		</table>
      </div>
    </div>
  </div>
  
</div>
</body>
<div class="modal fade" id="alertModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" >
   <div class="modal-dialog">
      <div class="modal-content">
         <div class="modal-header">
            <h4 class="modal-title" id="myModalLabel">提示</h4>
         </div>
         <div class="modal-body">
         <progress id="progressBar" value="0" max="100"></progress>
  				<span id="percentage"></span> </div>
      </div>
	</div>
</div>
</html>

后台是Java

	@RequestMapping("/uploads")
	public String uploads(HttpServletRequest request,HttpServletResponse response){
		
		logger.debug("进入 DataAcquisitionController.uploads");
		//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全
		Date date=new Date();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
		StringBuffer path=new StringBuffer();
		path.append("/WEB-INF/upload/");
		path.append(sdf.format(date));
        String savePath = request.getSession().getServletContext().getRealPath(path.toString());
        //上传时生成的临时文件保存目录
        String tempPath = request.getSession().getServletContext().getRealPath("/WEB-INF/temp");
        File tmpFile = new File(tempPath);
        File saveFile = new File(savePath);
        if (!tmpFile.exists()) {
            //创建临时目录
            tmpFile.mkdir();
        }
        if(!saveFile.exists() && !saveFile.isDirectory()){
        	saveFile.mkdirs();
        }
        //消息提示
        String message = "";
        try{
            //使用Apache文件上传组件处理文件上传步骤:
            //1、创建一个DiskFileItemFactory工厂
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。
            factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
            //设置上传时生成的临时文件的保存目录
            factory.setRepository(tmpFile);
            //2、创建一个文件上传解析器
            ServletFileUpload upload = new ServletFileUpload(factory);
            //监听文件上传进度
            upload.setProgressListener(new ProgressListener(){
                public void update(long pBytesRead, long pContentLength, int arg2) {
                	logger.debug("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
                }
            });
             //解决上传文件名的中文乱码
//            upload.setHeaderEncoding("UTF-8"); 
            //3、判断提交上来的数据是否是上传表单的数据
            if(!ServletFileUpload.isMultipartContent(request)){
                //按照传统方式获取数据
            	request.setAttribute("msg", "form表单为空");
        		return "dataAcquisition";
            }
            
            //设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
            upload.setFileSizeMax(1024*1024);
            //设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
            upload.setSizeMax(1024*1024*10);
            //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
            List<FileItem> list = upload.parseRequest(request);
            DataAcquisitionPo dataAcquisitionPo=new DataAcquisitionPo();
            OperationDataPo operationDataPo=new OperationDataPo();
            for(FileItem item : list){
            	String name = item.getFieldName();
                //如果fileitem中封装的是普通输入项的数据
                if(item.isFormField()){
                    String value = item.getString();
                    if("remark".equals(name)){
                    	dataAcquisitionPo.setRemark(value);
                    }
                    if("deviceTotal".equals(name)){
                    	dataAcquisitionPo.setDeviceTotal(value);
                    	operationDataPo.setCount(Integer.valueOf(value));
                    }
                }else{//如果fileitem中封装的是上传文件
                    //得到上传的文件名称,
                    String filename = item.getName();
                    filename=java.net.URLDecoder.decode(filename,"UTF-8");
                    logger.debug("filename:"+filename);
                    if(filename==null || filename.trim().equals("")){
                        continue;
                    }
                    //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:  c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
                    //处理获取到的上传文件的文件名的路径部分,只保留文件名部分
                    filename = filename.substring(filename.lastIndexOf("\\")+1);
                    //得到上传文件的扩展名
                    String fileExtName = filename.substring(filename.lastIndexOf(".")+1);
                    //如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法
                    logger.debug("上传的文件的扩展名是:"+fileExtName);
                    //获取item中的上传文件的输入流
                    InputStream in = item.getInputStream();
                    //得到文件保存的名称
                    SimpleDateFormat sd=new SimpleDateFormat("yyyyMMddhhmmssSSS");
                    Date dating=new Date();
                    String saveFilename = sd.format(dating)+"."+fileExtName;
//                    String saveFilename = sd.format(dating) + "_" + filename;
                    //创建一个文件输出流
                    FileOutputStream out = new FileOutputStream(savePath + "\\" + saveFilename);
                    if("enterFile".equals(name)){
                    	dataAcquisitionPo.setAttachmentEnterprise(savePath + "\\" + saveFilename);
                    }
                    if("deviceFile".equals(name)){
                    	dataAcquisitionPo.setAttachmentDevice(savePath + "\\" + saveFilename);;
                    }
                    //创建一个缓冲区
                    byte buffer[] = new byte[1024];
                    //判断输入流中的数据是否已经读完的标识
                    int len = 0;
                    //循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据
                    while((len=in.read(buffer))>0){
                        //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中
                        out.write(buffer, 0, len);
                    }
                    //关闭输入流
                    in.close();
                    //关闭输出流
                    out.close();
                    //删除处理文件上传时生成的临时文件
                    //item.delete();
                    message = "文件上传成功!";
                }
            }
            String userName=((UserPo) request.getSession().getAttribute("user")).getUserName();
            dataAcquisitionPo.setOperator(userName);
//            dataAcquisitionService.insert(dataAcquisitionPo);
            
            operationDataService.insert(operationDataPo);
        }catch (FileUploadBase.FileSizeLimitExceededException e) {
            e.printStackTrace();
            request.setAttribute("msg", "单个文件超出最大值!!!");
    		return "dataAcquisition";
        }catch (FileUploadBase.SizeLimitExceededException e) {
            e.printStackTrace();
            request.setAttribute("msg", "上传文件的总的大小超出限制的最大值!!!");
            return "dataAcquisition";
        }catch (Exception e) {
            message= "文件上传失败!";
            e.printStackTrace();
        }
		request.setAttribute("msg", message);
		return "dataAcquisition";
	}

第三种 用Ajax和FormData

function doUpload() {
	var fileObj1 = document.getElementById("enterFile").files[0]; // js 获取文件对象
    var fileObj2 = document.getElementById("deviceFile").files[0]; // js 获取文件对象
    var fileObj3 = $("#deviceTotal").val(); // js 获取文件对象
    var FileController = "${pageContext.request.contextPath}/mvc/dataAcquisition/uploads";                    // 接收上传文件的后台地址 
    // FormData 对象
    var form = new FormData();
    //form.append("author", "hooyes");                        // 可以增加表单数据

    form.append("enterFile", fileObj1);                           // 文件对象
    form.append("deviceFile", fileObj2);                           // 文件对象
    form.append("deviceTotal", fileObj3);                           // 文件对象
	$.ajax({
		url: contextPath + "/mvc/dataAcquisition/doUploads",
		type: "post",
		data: form,
		dataType : "json",
		//async: false,
		contentType: false, //不加后台会报异常FileUploadBase$InvalidContentTypeException
		processData: false, //不加前台会报错Illegal invocation
		success: function(data){
			alert(data.msg);
		},
		error: function(data) {
			alert("操作失败!!!");
		}
	});
}


第四种 用jquery.form.js里的ajaxForm(我没成功,有兴趣的可以用用)

猜你喜欢

转载自blog.csdn.net/caide3/article/details/77850744