HTML5 jQuery+FormData 异步上传文件,带进度条

利用jQuery和html5的FormData异步上传文件的好处是:

  • 实现很简单
  • 很方便地支持进度条
  • 很方便地进行扩展和美化

先看看效果图:


图片上传后的结果:



实现步骤如下:

第一步:配置好SpringMVC + servlet3.0 文件上传所需要的各种资源,参考:http://blog.csdn.net/clementad/article/details/49533189


第二步:上传页面的html代码:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <link href="../resources/css/common.css" rel="stylesheet" />
  6. <script src="../resources/js/jquery-2.1.4.js"></script>
  7. </head>
  8. <body>
  9. <h2>HTML5异步上传文件,带进度条</h2>
  10. <form method="post" enctype="multipart/form-data">
  11. 其他需要提交的信息:<input type="text" name="otherInfo"/><br/><br/>
  12. 选择要上传的文件:<br/>
  13. <input type="file" name="file" /><span></span><br/>
  14. <input type="file" name="file" /><span></span><br/>
  15. </form>
  16. <br/><br/>
  17. <input type="button" value="上传吧" onclick="upload()"/>
  18. <br/><br/>
  19. 上传进度:<progress></progress><br/>
  20. <p id="progress">0 bytes</p>
  21. <p id="info"></p>
  22. </body>
  23. </html>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<link href="../resources/css/common.css" rel="stylesheet" />
	<script src="../resources/js/jquery-2.1.4.js"></script>
	
</head>

<body>
	<h2>HTML5异步上传文件,带进度条</h2>
	<form method="post" enctype="multipart/form-data">
		其他需要提交的信息:<input type="text" name="otherInfo"/><br/><br/>
		选择要上传的文件:<br/>
		<input type="file" name="file" /><span></span><br/>
		<input type="file" name="file" /><span></span><br/>
	</form>
	
	<br/><br/>
	<input type="button" value="上传吧" οnclick="upload()"/>
	<br/><br/>
	上传进度:<progress></progress><br/>
	<p id="progress">0 bytes</p>
	<p id="info"></p>
</body>
</html>


第三步:异步上传的JavaScript代码(注释很详细):

  1. <script>
  2. var totalSize = 0;
  3. //绑定所有type=file的元素的onchange事件的处理函数
  4. $(':file').change(function() {
  5. var file = this.files[0]; //假设file标签没打开multiple属性,那么只取第一个文件就行了
  6. name = file.name;
  7. size = file.size;
  8. type = file.type;
  9. url = window.URL.createObjectURL(file); //获取本地文件的url,如果是图片文件,可用于预览图片
  10. $(this).next().html("文件名:" + name + " 文件类型:" + type + " 文件大小:" + size + " url: " + url);
  11. totalSize += size;
  12. $("#info").html("总大小: " + totalSize + "bytes");
  13. });
  14. function upload() {
  15. //创建FormData对象,初始化为form表单中的数据。需要添加其他数据可使用formData.append("property", "value");
  16. var formData = new FormData($('form')[0]);
  17. //ajax异步上传
  18. $.ajax({
  19. url: "http://localhost:8080/MyJavaStudio/servlet/file/upload",
  20. type: "POST",
  21. data: formData,
  22. xhr: function(){ //获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
  23. myXhr = $.ajaxSettings.xhr();
  24. if(myXhr.upload){ //检查upload属性是否存在
  25. //绑定progress事件的回调函数
  26. myXhr.upload.addEventListener('progress',progressHandlingFunction, false);
  27. }
  28. return myXhr; //xhr对象返回给jQuery使用
  29. },
  30. success: function(result){
  31. $("#result").html(result.data);
  32. },
  33. contentType: false, //必须false才会自动加上正确的Content-Type
  34. processData: false //必须false才会避开jQuery对 formdata 的默认处理
  35. });
  36. }
  37. //上传进度回调函数:
  38. function progressHandlingFunction(e) {
  39. if (e.lengthComputable) {
  40. $('progress').attr({value : e.loaded, max : e.total}); //更新数据到进度条
  41. var percent = e.loaded/e.total*100;
  42. $('#progress').html(e.loaded + "/" + e.total+" bytes. " + percent.toFixed(2) + "%");
  43. }
  44. }
  45. </script>
<script>
	var totalSize = 0;
	
	//绑定所有type=file的元素的onchange事件的处理函数
	$(':file').change(function() {
		var file = this.files[0]; //假设file标签没打开multiple属性,那么只取第一个文件就行了
		name = file.name;
		size = file.size;
		type = file.type;
		url = window.URL.createObjectURL(file); //获取本地文件的url,如果是图片文件,可用于预览图片
		
		$(this).next().html("文件名:" + name + " 文件类型:" + type + " 文件大小:" + size + " url: " + url);
		
		totalSize += size;
		
		$("#info").html("总大小: " + totalSize + "bytes");
		
	});

	function upload() {
		//创建FormData对象,初始化为form表单中的数据。需要添加其他数据可使用formData.append("property", "value");
		var formData = new FormData($('form')[0]);
		
		//ajax异步上传
		$.ajax({
			url: "http://localhost:8080/MyJavaStudio/servlet/file/upload",
			type: "POST",
			data: formData,
			xhr: function(){ //获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
			
				myXhr = $.ajaxSettings.xhr();
				if(myXhr.upload){ //检查upload属性是否存在
					//绑定progress事件的回调函数
					myXhr.upload.addEventListener('progress',progressHandlingFunction, false); 
				}
				return myXhr; //xhr对象返回给jQuery使用
			},
			success: function(result){
				$("#result").html(result.data);
			},
			contentType: false, //必须false才会自动加上正确的Content-Type
			processData: false  //必须false才会避开jQuery对 formdata 的默认处理
		});
	}		

	//上传进度回调函数:
	function progressHandlingFunction(e) {
		if (e.lengthComputable) {
			$('progress').attr({value : e.loaded, max : e.total}); //更新数据到进度条
			var percent = e.loaded/e.total*100;
			$('#progress').html(e.loaded + "/" + e.total+" bytes. " + percent.toFixed(2) + "%");
		}
	}
</script>

第四步:SpringMVC写好接受和保持文件的Controller方法:

  1. /**
  2. * 文件上传
  3. * @author XuJijun
  4. *
  5. */
  6. @RestController
  7. @RequestMapping("/servlet/file")
  8. public class FileUploadController {
  9. /**
  10. * 保存文件的目录,放在web目录、或一个指定的绝对目录下
  11. */
  12. private static final String SAVE_DIR = "uploadFiles";
  13. /**
  14. *
  15. * @param request
  16. * @param response
  17. * @param p form表单中,type="text"的input控件,内容通过这个参数传送过来,以input控件中的name属性来区分
  18. * @return JSON表示的处理结果
  19. * @throws ServletException
  20. * @throws IOException
  21. */
  22. @RequestMapping("/upload")
  23. public JsonResult upload(HttpServletRequest request, HttpServletResponse response, @RequestParam Map<String, Object> p)
  24. throws ServletException, IOException {
  25. // 获取 web application的绝对路径
  26. String appPath = request.getServletContext().getRealPath("");
  27. // 构造文件存放的路径
  28. String savePath = appPath + File.separator + SAVE_DIR;
  29. // 如果文件存放路径不存在,则mkdir一个
  30. File fileSaveDir = new File(savePath);
  31. if (!fileSaveDir.exists()) {
  32. fileSaveDir.mkdirs();
  33. }
  34. List<String> fileNames = new ArrayList<>();
  35. //循环所有的part,把part中的文件保存到硬盘中
  36. for (Part part : request.getParts()) {
  37. String fileName = part.getSubmittedFileName();
  38. //form表单中的每个input,都在一个不同的part中,
  39. //所以需要判断通过fileName是否为空,过滤掉其他类型的input(比如type="text"):
  40. if(!StringUtils.isEmpty(fileName)){
  41. part.write(savePath + File.separator + fileName);
  42. fileNames.add(fileName);
  43. }
  44. }
  45. Map<String, Object> resultData = new HashMap<>();
  46. resultData.put("savePath", savePath);
  47. resultData.put("files", fileNames);
  48. return new JsonResult("200", "文件上传成功!", resultData);
  49. }
  50. /**
  51. * 从content-disposition头中获取源文件名
  52. *
  53. * content-disposition头的格式如下:
  54. * form-data; name="dataFile"; filename="PHOTO.JPG"
  55. *
  56. * @param part
  57. * @return
  58. */
  59. @SuppressWarnings("unused")
  60. private String extractFileName(Part part) {
  61. String contentDisp = part.getHeader("content-disposition");
  62. String[] items = contentDisp.split(";");
  63. for (String s : items) {
  64. if (s.trim().startsWith("filename")) {
  65. return s.substring(s.indexOf("=") + 2, s.length()-1);
  66. }
  67. }
  68. return "";
  69. }
  70. }
/**
 * 文件上传
 * @author XuJijun
 *
 */
@RestController
@RequestMapping("/servlet/file")
public class FileUploadController {
	
	/**
	 * 保存文件的目录,放在web目录、或一个指定的绝对目录下
	 */
	 private static final String SAVE_DIR = "uploadFiles";
	
	 /**
	  * 
	  * @param request
	  * @param response
	  * @param p form表单中,type="text"的input控件,内容通过这个参数传送过来,以input控件中的name属性来区分
	  * @return JSON表示的处理结果
	  * @throws ServletException
	  * @throws IOException
	  */
	@RequestMapping("/upload")
	public JsonResult upload(HttpServletRequest request, HttpServletResponse response, @RequestParam Map<String, Object> p)
			throws ServletException, IOException {

		// 获取 web application的绝对路径
		String appPath = request.getServletContext().getRealPath("");
		
		// 构造文件存放的路径
		String savePath = appPath + File.separator + SAVE_DIR;

		// 如果文件存放路径不存在,则mkdir一个
		File fileSaveDir = new File(savePath);
		if (!fileSaveDir.exists()) {
			fileSaveDir.mkdirs();
		}

		List<String> fileNames = new ArrayList<>();
		
		//循环所有的part,把part中的文件保存到硬盘中
		for (Part part : request.getParts()) {
			String fileName = part.getSubmittedFileName();
			
			//form表单中的每个input,都在一个不同的part中,
			//所以需要判断通过fileName是否为空,过滤掉其他类型的input(比如type="text"):
			if(!StringUtils.isEmpty(fileName)){ 
				part.write(savePath + File.separator + fileName);
				fileNames.add(fileName);
			}
		}

		Map<String, Object> resultData = new HashMap<>();
		resultData.put("savePath", savePath);
		resultData.put("files", fileNames);
		
		return new JsonResult("200", "文件上传成功!", resultData);
	}
	 
	/**
	 * 从content-disposition头中获取源文件名
	 * 
	 * content-disposition头的格式如下:
	 * form-data; name="dataFile"; filename="PHOTO.JPG"
	 * 
	 * @param part
	 * @return
	 */
	@SuppressWarnings("unused")
	private String extractFileName(Part part) {
	    String contentDisp = part.getHeader("content-disposition");
	    String[] items = contentDisp.split(";");
	    for (String s : items) {
	        if (s.trim().startsWith("filename")) {
	            return s.substring(s.indexOf("=") + 2, s.length()-1);
	        }
	    }
	    return "";
	}

}

最后那个私有方法可以不用的,只是为了演示如何直接获取request header中的数据。


最后,验证上传过程中的网络消息:

上传的消息头和数据:


可见,对于表单中的3个input,http request payload中对应有3个part来上传数据。

关于http协议的更多介绍,可参考:http://blog.csdn.net/clementad/article/details/41620765


Controller处理后的返回结果(JSON格式):


总结:代码很简单,结果很友好。感谢HTML5和SpringMVC!


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 可以使用Java和jQuery编写一个进度条的文件上传程序,具体步骤如下:1. 使用Java编写一个文件上传服务,它将接收文件上传请求,并将文件保存到服务器上。2.使用jQuery编写一个简单的表单,它允许用户上传文件。3.使用jQuery的AJAX函数,将用户上传的文件发送到Java文件上传服务。4.使用jQuery进度条插件,显示文件上传的进度。 ### 回答2: 要实现一个进度条的上传程序,我们可以使用Java和jQuery进行开发。 首先,我们需要在后端使用Java编写一个文件上传的接口。可以使用Java的Servlet或Spring MVC框架来实现。这个接口应该能够接收到前端发送的文件,并将其保存到服务器的指定位置。 在前端,我们可以使用jQuery的ajax方法来发送文件到后端接口。在发送请求之前,我们可以使用HTML的input元素创建一个文件选择器,让用户选择要上传的文件。 一旦用户选择了文件,我们可以使用FileReader对象来读取文件的内容,并将其作为数据传递给后端接口。在发送请求时,我们可以通过使用FormData对象,将文件数据添加到表单数据中,并设置请求方法为POST。 在发送请求的同时,我们可以使用XMLHttpRequest的onprogress事件来监听上传的进度。这个事件会在上传过程中不断触发,并返回一个event对象,其中包含有关上传进度的信息,如已上传的字节数和总字节数。我们可以利用这些信息来计算上传的百分比,并更新进度条的宽度。 在接收到后端返回的响应后,我们可以根据情况进行相应的处理,如显示上传成功的提示信息或显示上传失败的错误信息。 最后,我们还可以使用jQuery来实现进度条的动画效果。可以通过设置进度条的初始宽度和动态调整宽度的方式来实现。可以使用jQuery的animate方法来实现平滑的宽度过渡效果。 综上所述,通过使用Java和jQuery,我们可以实现一个进度条的上传程序,方便用户上传文件并实时显示上传进度。 ### 回答3: 要实现一个进度条的上传程序,可以使用Java和jQuery来完成。下面是一个简单的实现思路: 1. 在前端页面使用HTML和jQuery创建一个上传表单,并添加一个进度条元素用于展示上传进度。 2. 在后端使用Java编写一个接受上传文件的Servlet。该Servlet处理上传请求,并在上传过程中不断更新进度。 3. 在前端页面中,使用jQuery的Ajax方法来发送上传请求,将文件数据以formData的形式发送到后端Servlet。 4. 后端Servlet接收到上传请求后,创建一个输入流来读取上传的文件数据,并根据文件大小计算总进度。 5. 在读取文件数据的过程中,通过不断更新进度,将当前进度发送回前端页面。 6. 前端页面接收到后端发送的进度数据后,更新进度条的显示。 7. 当文件数据读取完成后,后端Servlet将文件保存到指定位置,并向前端页面发送上传完成的消息。 8. 前端页面接收到上传完成的消息后,可以显示上传成功的提示。 这样,我们就完成了一个进度条的上传程序。通过Java和jQuery的结合,我们能够实现前后端的数据交互和进度更新,让用户可以清楚地看到文件上传的进度。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值