ajax upload file with progress bar

This case uses ajax + springmvc

 1. The first way

The first one uses ajax formData. In this way, ie9 does not support formData, so ie9 is not used in this way (ie10 and ie10+ are not tested)

html:

<style>
	#prograssbarBorder{
		width:500px;
		height:30px;
		border:1px solid #B2B2B2;
		border-radius:50px 50px 50px 50px;
	}
	#prograssbar {
		width:0px;
		height:30px;
		background:#00D328;
		border-radius:50px 50px 50px 50px;
	}
</style>

<script>
	var xhr;
	if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
		xhr = new XMLHttpRequest();
	} else {// code for IE6, IE5
		xhr = new ActiveXObject("Microsoft.XMLHTTP");
	}

	$(function() {
		$("#testInfoForm").submit(function() {

			var fileData = document.getElementById('uploadFile').files[0];
			var formData = new FormData();
			xhr.open('post', 'testSaveUpload.do', true);
			xhr.onreadystatechange = function() {
				if (this.readyState == 4) {
					//0: request not initialized
					//1: The server connection has been established
					//2: request received
					//3: request processing
					//4: The request is complete and the response is ready
					document.getElementById('prograssbar').style.width = 100 + '%';
					document.getElementById('precent').innerHTML = Math.floor(100) + '%';
				}
			}
			xhr.upload.onprogress = function(ev) {
				if (ev.lengthComputable) {
					var precent = 100 * ev.loaded / ev.total;
					if(100 == precent){
						document.getElementById('prograssbar').style.width = 99.9 + '%';
						document.getElementById('precent').innerHTML = Math.floor(99.9) + '%';
					}else{
						document.getElementById('prograssbar').style.width = precent + '%';
						document.getElementById('precent').innerHTML = Math.floor(precent) + '%';
					}
					
					
				}
			}
			formData.append('uploadFile', fileData);
			xhr.send(formData);

			return false;
		});
	})
</script>



<div>

	<div id="prograssbarBorder">
        <div id="prograssbar"></div>
    </div>
    <span id="precent"></span><br/>
    
    
	<form id="testInfoForm" enctype="multipart/form-data">
		<div>
			<table>
				<tr>
					<td>Upload file</td>
					<td><input type="file" id="uploadFile" name="uploadFile"
						class="InputStyle" /> *</td>
				</tr>

			</table>
		</div>
		<div>
			<input type="submit" id="saveBtn" />
		</div>
	</form>
</div>

 

 

2. The second way

 

The second method uses ajaxform and uses ajxasubmit to handle it. This method supports ie9 (only supports file upload, but does not support progress bar display). Similarly, ie10 and ie10+ have not been tested.

 

html:

Note: The second method needs to introduce juqery.form.js

<script type="text/javascript" src="js/jquery.form.js"></script>
<style>
#prograssbarBorder {
	width: 500px;
	height: 30px;
	border: 1px solid #B2B2B2;
	border-radius: 50px 50px 50px 50px;
}

#prograssbar {
	width: 0px;
	height: 30px;
	background: #00D328;
	border-radius: 50px 50px 50px 50px;
}
</style>

<script>
	
	
	function onprogress(ev){
		if (ev.lengthComputable) {
			var precent = 100 * ev.loaded / ev.total;
			if(100 == precent){
				document.getElementById('prograssbar').style.width = 99.9 + '%';
				document.getElementById('precent').innerHTML = Math.floor(99.9) + '%';
			}else{
				document.getElementById('prograssbar').style.width = precent + '%';
				document.getElementById('precent').innerHTML = Math.floor(precent) + '%';
			}
		}
    }
	
	function onreadystatechange(ev){
		if (this.readyState == 4) {
			//0: request not initialized
			//1: The server connection has been established
			//2: request received
			//3: request processing
			//4: The request is complete and the response is ready
			document.getElementById('prograssbar').style.width = 100 + '%';
			document.getElementById('precent').innerHTML = Math.floor(100) + '%';
		}
    }
	
	
	$(function() {
		
		
		/* $('#testInfoForm').ajaxForm(function(){
			 
			 
		}); */
		$("#testInfoForm").submit(function() {
			var option = {
				url: 'testSaveUpload.do',
				type : "post",
				async : true, //must be asynchronous, otherwise the progress bar will not be displayed
				
				success : function(data) {
					var aa = "aaa";
				},
			 	xhr : function(){
	                var xhr = $ .ajaxSettings.xhr ();
	                if(onprogress && xhr.upload) {
	                    xhr.upload.addEventListener("progress" , onprogress, false);
	                }
	                xhr.addEventListener("readystatechange",onreadystatechange,false);
	                return xhr;
	                
	            },
	            
			};
			
			$("#testInfoForm").ajaxSubmit(option);
			

			return false;
		});
	})
</script>



<div>

	<div  id="prograssbarBorder">
		<div  id="prograssbar"></div>
	</div>
	<span id="precent"></span><br />


	<form id="testInfoForm" enctype="multipart/form-data">
		<div>
			<table>
				<tr>
					<td>Upload file</td>
					<td><input type="file" id="uploadFile" name="uploadFile"
						class="InputStyle" /> *</td>
				</tr>

			</table>
		</div>
		<div>
			<input type="submit" id="saveBtn" />
		</div>
	</form>
</div>

 

 

Backstage:

@RequestMapping(value="testSaveUpload")
	public void testSaveUpload(HttpServletRequest request,HttpServletResponse response) throws Exception{
		response.setContentType("text/html");
		MultipartHttpServletRequest multiPartRequest =  (MultipartHttpServletRequest) (request instanceof MultipartHttpServletRequest ? request : null) ;
		MultipartFile uploadFile = multiPartRequest.getFile("uploadFile");
		String originalFilename = uploadFile.getOriginalFilename();
		String subfix = originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());
		File filePaht = new File("D:\\TestM\\Exam\\"+UUID.randomUUID().toString()+subfix);
		uploadFile.transferTo(filePaht);
		response.setStatus(HttpServletResponse.SC_OK);
		response.getOutputStream().println("aaa");
	}
	

 

 

 3. The third way

 The third method is to use the foreground to continuously send requests to the background, and the background uses threads to return the read files to the foreground, which is compatible with ie9. Ajaxform is also used, and ajxasubmit is used to submit. Need to import juqery.form.js

html:

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ include file="/common/common.jsp"%>
<%@ include file="/common/tips.jsp"%>

<script type="text/javascript" src="js/jquery.form.js"></script>
<style>
#prograssbarBorder {
	width: 500px;
	height: 30px;
	border: 1px solid #B2B2B2;
	border-radius: 50px 50px 50px 50px;
}

#prograssbar {
	width: 0px;
	height: 30px;
	background: #00D328;
	border-radius: 50px 50px 50px 50px;
}
</style>

<script>
	
	
	$(function() {
		
		$("#testInfoForm").submit(function() {
			
			var option = {
				url: 'testSaveUpload.do',
				type : "post", 
				success : function(data) {
					// requestStatus+",,,"+threadId+",,,"threadStatus
					var requestStatus = data.split(",,,")[0];
					var currentThreadId = data.split(",,,")[1];
					var threadStatus = data.split(",,,")[2];
					var totalSize = data.split(",,,")[3];
					var readSize = data.split(",,,")[4];
					if(requestStatus == 'running'){//未完成,正在运行
						$("#threadId").val(currentThreadId);
						var precent = 100 * readSize / totalSize;
						document.getElementById('prograssbar').style.width = precent + '%';
						document.getElementById('precent').innerHTML = Math.floor(precent) + '%';
					}else if(requestStatus == 'success'){ //上传完成,成功
						$("#threadId").val("");
						clearInterval(myInterval);
						document.getElementById('prograssbar').style.width = 100 + '%';
						document.getElementById('precent').innerHTML = Math.floor(100) + '%'; 
					}else if(requestStatus == 'failed'){ //上传失败
						$("#threadId").val("");
						clearInterval(myInterval);
					}else{
						$("#threadId").val("");
						clearInterval(myInterval);
					}
				},
				error : function (){
					$("#threadId").val("");
					clearInterval(myInterval);
				},
	            
			};
			
			
			var myInterval =setInterval(function(){
				var threadId = $("#threadId").val();
				$("#testInfoForm").ajaxSubmit(option);
			},500);
	
			return false;
		});
			
			
			
		
		
		
		
		
		
		
		
		
		
		
	})
</script>



<div>

	<div  id="prograssbarBorder">
		<div  id="prograssbar"></div>
	</div>
	<span id="precent"></span><br />

	
	<form id="testInfoForm" enctype="multipart/form-data">
	
		<input type="hidden" id="threadId" name="threadId" /> 
		<div>
			<table>
				<tr>
					<td>上传文件</td>
					<td><input type="file" id="uploadFile" name="uploadFile"
						class="InputStyle" /> *</td>
				</tr>

			</table>
		</div>
		<div>
			<input type="submit" value="提交" id="saveBtn" />
		</div>
	</form>
</div>
 

 

 

后台:

 

 

@RequestMapping(value="testSaveUpload") 
	public void testSaveUpload(HttpServletRequest request,HttpServletResponse response,String threadId) throws Exception{
		MultipartHttpServletRequest multiPartRequest =  (MultipartHttpServletRequest) (request instanceof MultipartHttpServletRequest ? request : null) ;
		MultipartFile uploadFile = multiPartRequest.getFile("uploadFile");
		String originalFilename = uploadFile.getOriginalFilename();
		String subfix = originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());
	
		InputStream input = uploadFile.getInputStream();
		//总大小
		long totleSize = uploadFile.getSize();
		System.out.println("总大小:---》"+totleSize);
		
		long readSum = 0l;
		if(StringUtils.isNotBlank(threadId)){ //当前线程正在运行
			ReadFileThread readFileThread = (ReadFileThread) ConstantMap.constantMap.get(threadId);
			//获取已读大小
			long readSize = readFileThread.getReadSum();
			//线程状态
			String threadStatus = readFileThread.getThreadStatus();
			if("completed".equals(threadStatus)){ //线程已经运行完毕
				ConstantMap.constantMap.remove(threadId);
				response.getOutputStream().println("success,,,"+threadId+",,,"+threadStatus+",,,"+totleSize+",,,"+readSize);
				return ;
			}else if("error".equals(threadStatus)){ //出错
				ConstantMap.constantMap.remove(threadId);
				response.getOutputStream().println("failed,,,"+threadId+",,,"+threadStatus+",,,"+totleSize+",,,"+readSize);
				return ;
			}else if("uncompleted".equals(threadStatus)){ //未完成
				response.getOutputStream().println("running,,,"+threadId+",,,"+threadStatus+",,,"+totleSize+",,,"+readSize);
				return ;
			}
			return ;
		}else{ // 一个新的请求
			File filePaht = new File("D:\\TestM\\Exam\\"+UUID.randomUUID().toString()+subfix);
			//文件夹不存在就创建
			if(!filePaht.getParentFile().exists()){
				filePaht.getParentFile().mkdirs();
			}
			FileOutputStream output = new FileOutputStream(filePaht);
			threadId = UUID.randomUUID().toString();
			
			//创建一个新的线程
			ReadFileThread readFileThread = new ReadFileThread(input, output,readSum);
			Thread thread = new Thread(readFileThread);
			thread.start();
			//获取已读大小
			long readSize = readFileThread.getReadSum();
			//线程状态
			String threadStatus = readFileThread.getThreadStatus();
			if("completed".equals(threadStatus)){ //线程已经运行完毕
				ConstantMap.constantMap.remove(threadId);
				System.out.println("end");
				response.getOutputStream().println("success,,,"+threadId+",,,"+threadStatus+",,,"+totleSize+",,,"+readSize);
				return ;
			}else if("error".equals(threadStatus)){ //出错
				ConstantMap.constantMap.remove(threadId);
				response.getOutputStream().println("failed,,,"+threadId+",,,"+threadStatus+",,,"+totleSize+",,,"+readSize);
				return ;
			}else if("uncompleted".equals(threadStatus)){ //未完成
				ConstantMap.constantMap.put(threadId, readFileThread);
				response.getOutputStream().println("running,,,"+threadId+",,,"+threadStatus+",,,"+totleSize+",,,"+readSize);
				return ;
			}
		}
		return ;
		
	}
 

 

 

class ReadFileThread implements Runnable{
		
		InputStream input;
		FileOutputStream output;
		String threadStatus = "uncompleted";
		long readSum;
		
		public String getThreadStatus() {
			return threadStatus;
		}
		public void setThreadStatus(String threadStatus) {
			this.threadStatus = threadStatus;
		}
		
		public Long getReadSum() {
			return readSum;
		}
		
		public ReadFileThread(InputStream input,FileOutputStream output, Long readSum) {
			this.input = input;
			this.output = output;
			this.readSum = readSum;
		}
		@Override
		public void run() {
			int readLength = 0;
			byte[] buffer = new byte[1444]; 
			try {
				while ( (readLength = input.read(buffer)) != -1) { 
					readSum += readLength; 
					System.out.println("已读大小:--》"+readSum);
					output.write(buffer, 0, readLength); 
				} 
			} catch (Exception e) {//出错
				this.setThreadStatus("error");
			}finally{
				try {//完成,成功
					this.setThreadStatus("completed");
					if(null != output){
						output.close();
					}
					if(null != output){
						input.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
				
			}
		}
		
	}
 

 

package com.exam.bean.common;

import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ConstantMap {
	//此处使用 hashtable ,防止并发问题
	public static Hashtable<String, Object> constantMap = new Hashtable<>();
	
	public static void setConstantMap(String key,Object value){
		if(constantMap.containsKey(key)){
			constantMap.remove(key);
			constantMap.put(key, value);
		}else{
			constantMap.put(key, value);
		}
	}
	
	public static Object getConstantMap(String key){
		Pattern pattern = Pattern.compile("\r\n");
		Matcher matcher = pattern.matcher(key);
		key = matcher.replaceAll("");
		if(constantMap.containsKey(key)){
			return constantMap.get(key);
		}
		return null;
	}
	
	public static Object removeConstantMap(String key){
		if(constantMap.containsKey(key)){
			return constantMap.remove(key);
		}
		return null;
	}
	
	
	
	
}

 

 

 

 

 

 

 

 

运行效果如下:



 

 

 

 另外附上:juqery.form.js

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326121911&siteId=291194637