最近一个项目要做大的视频文件的上传和下载。本来以前的项目框架里已经有现成的代码了,是用的springMVC文件上传下载的框架,但是以前都传的小文件,没什么问题,这次需要上传大文件,就老是报错了。
搜索原因的时候,发现好像这套框架是网络里面流传得比较广的,也算是bug吧,所以贴出来了。
可惜,看不到上传文件的源码,(因为源码在领导那里,他老人家太忙)。反正最后就是各种折腾,然后找到原因了的。
原因:
看了代码,FileManagerAction里面的上传方法,应该是先将文件传到tomcat服务器的一个临时文件里面,再通过spring包内置的FileCopyUtils.copy(srcMFile.getBytes(), descFile)方法,将它复制到所要上传到的目标文件夹去。
这个copy方法调用了commons-fileupload包里DiskFileItem类的get()方法,其中有一句代码是
byte[] fileData = new byte[(int) getSize()];
而这其中的getSize()方法的返回值是上文提到的copy方法的第一个参数srcMFile.getBytes()的值,也就是整个文件的大小的字节数。以前文件比较小的时候倒没什么关系,new了一个比较小长度的byte[]还能撑住,可是文件大了的时候,就不行了,就内存溢出了。
找到原因了要怎么解决呢,反正脑子是不够用了,所以就索性yahoo了一把。(没了谷歌,也就只有yahoo了)。然后看到了这篇问答,多少有点启发。
解决办法:
FileCopyUtils的copy方法有几个重载的方法,选择用参数为IO流的方法就不会报错。即是改为:
FileCopyUtils.copy(srcMFile.getInputStream(),new FileOutputStream(destFile));
就OK 了。
问题:
虽然这样解决了大文件上传的问题,但是因为文件比较大,copy的耗时可能会比较长,用户体验度有待改善。
============================================================================================
另外,之前还遇到过一个报错SizeLimitExceedException,这个和配置文件里设置的文件大小有关系。在multipartResolver那个bean里配置的。
搜索原因的时候,发现好像这套框架是网络里面流传得比较广的,也算是bug吧,所以贴出来了。