【JAVA & JavaScript】SpringMVC 中使用 commons-fileupload 与 ajax 上传文件时遇到的一个问题

使用 SpringMVC, 在做一个图片上传功能时遇到一个比较奇怪的问题,记录一下,请大佬多指教。

功能描述

点击"上传"按钮,选择一张图片,点击"提交"按钮,提交到后台,保存到服务器"web-app/upload/image"目录下,将文件路径保存至数据库,成功后返回该路径到前台,JS 写入 img 的 src 属性显示。

问题描述

后台 Java 代码依次执行保存图片、写入路径到DB、返回 AjaxResponse 信息。前台 ajax 在 success 回调函数中将 Java 后台返回的路径写入 img 的 src 属性。
报错 404。无法找到指定资源。
手动复制资源路径可以打开图片。

主要代码(非完整,但基本能看明白意思)

$.ajax({
    type : $form.attr('method') || 'POST',
    url : $form.attr('action'),
    data : new FormData($form[0]),
    cache : false,
    dataType : 'json',
    contentType : false,
    processData : false,
	    success : function(json) {
	     	console.info(json);
		     if (json.statusCode === 200) {
		      //sleep(2000);
		      //console.info("ajax success: "+new Date().getTime());
		      $('#headImg').attr('src', json.map.headImg+"?v="+Math.random());
		     } else {
		     }
		    },	
	error : function(e) {
     	console.error(e);
    }
/*获取文件信息*/
public UploadFileManager getFiles(HttpServletRequest request) {
	if (request instanceof MultipartRequest == false) {
	   request = new MultipartRequest(request);
	  }
	return ((MultipartRequest)request).getFileManager();
 }

/*上传文件*/ 
@RequestMapping("saveHeadImg")
@ResponseBody
 public AjaxResponse savaHeadImg(HttpServletRequest request) {
	  AjaxResponse response = AjaxResponseUtils.getFailureResponse();//初始化返回信息。默认失败 STATUS = 300
	  //获取上传文件管理器
	  UploadFileManager fileManager = getFiles(request);
	  UploadFile file = fileManager.getFile();
	  fileManager.save();
  	  //System.out.println("file save success: "+System.currentTimeMillis());  	  
  	  //保存上传路径到数据库
  	  Users update = new Users();
	  update.setId(1);
	  update.setHeadImg(file.getCompleteName());
	  this.userService.update(update);
	  //System.out.println("insert db success: " + System.currentTimeMillis());
	  response = AjaxResponseUtils.getSuccessResponse();//保存成功返回信息。STATUS = 200
	  response.put("headImg", file.getCompleteName());//写入图片路径
	  //System.out.println("return : " + System.currentTimeMillis());
	  return response;
}

调试过程

1、正常运行时报错找不到资源。

GET http://localhost:8080/Maven4Web/upload/201905157897d8075d944702a32b61d04426944e.jpg?v=0.24819909817403518 404 (Not Found)

img

2、直接复制 url 到地址栏打开可以正常访问图片

pic1

这里初步判断可能是因为代码执行顺序问题导致前端页面访问图片地址时,服务器端的图片还未上传成功?

3、Java 代码中断点调试发现执行顺序正常。先保存图片到服务器(文件夹中已经可以看到文件),保存成功后写入路径到数据库,最后返回 response 对象。

也就是说,JS 代码 ajax 请求中的 success 回调方法执行时,图片已经是确定成功保存在服务器目录中的。那为什么无法直接显示呢?

4、JS 代码 ajax 请求 success 回调函数中断点调试。发现也可以正常显示图片?

img2

这个现象很明显说明,在 success 回调方法中需要短暂的停顿后才可以正常加载图片。

5、为了验证猜想,在 success 方法中调用自定义的 sleep 方法,目的是让其休息 2 秒钟。运行,发现确实可以正常加载上传的图片
img3在这里插入图片描述

这说明,猜想似乎距离真相不远了。
以前也并非没有碰到过类似问题。只是,以前碰到类似问题,大多原因都是由于异步或者多线程等操作导致方法执行完成的顺序错乱。
比如,图片上传、保存到DB、页面加载图片路径这几个方法异步执行,可能会导致页面加载时图片还未保存完成,出现上述现象。
但这次的代码,后台并未进行多线程或异步操作,前端虽然是 Ajax 提交,但也是在后台执行完成后才触发 success 回调从而加载图片路径。
所以应该另有其他原因。

6、为了进一步确认方法触发的时间顺序,在前后端代码都分别加入了时间戳打印。先屏蔽 JS 中的 sleep 方法。运行。

信息: Reloading Context with name [/Maven4Web] is completed
file save success: 1557928478910
insert db success: 1557928479468
return : 1557928479468

ajax success: 1557928479524
GET http://localhost:8080/Maven4Web/upload/20190515047df2c0ae094269a790fdfc7dcd06e4.jpg?v=0.9551198420254206 404 (Not Found)

7、解开 sleep 方法。再次运行

file save success: 1557928663064
insert db success: 1557928663146
return : 1557928663146

ajax success: 1557928665157

总结

通过调试,可以确认的是,js 中修改 img 的 src 属性试图加载图片时,图片是确实已经成功保存在该路径下的。
但为什么立即加载图片会失败,延迟加载图片就可以成功?

因本人新手入门,才疏学浅。目前还未确认问题原因,后续还会继续测试,如有大佬知道问题所在,烦请指导一下,不胜感激。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HolaSecurity

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值