引言
最近工作上做的需求是整合两个项目的文件,将另外一个使用的servlet完成的两个接口的项目整合到springboot项目中。(文件上传和文件下载接口)
在整合的过程中遇到了许多问题,比如:spring中默认使用的MultipartFile
来进行文件的上传,但是那个servlet的项目中使用的是ServletFileUpload
来进行的文件上传,这就导致了如果使用springboot的方式写controller完成需求的话,无法从ServletFileUpload
中取到相关数据(springboot的MultipartFile不允许关闭,因为有其它接口使用的MultipartFile)。
查询了许多资料后,感觉有一个挺正确的答案,就是重写spring默认的MultipartFile
的isMultipart
接口,但是不知道为什么,配置到项目中还是不行。
后来经过leader的指导,发现在springboot
中使用servlet
的方式去完成的话是可以取到文件数据的,然后我就开始使用servlet
去完成需求,但是完成的过程中坑越来越多。
-
第一个遇到的坑就是:在
servlet
中使用req.getParameter()
获取不到值!!!,经过查询后,发现是因为表单是以form-data
提交的所以才取不到,那为什么我们平时在spring或springboot中就可以取到呢?因为spring内部跟我们做了很多操作,于是我就参考着网上的方法去调用spring内部的工具进行处理,处理完成后我发现普通表单提交的数据是可以取到了,但是文件数据又全丢失了!!害,这个时候不得不又开启谷歌大法,最后的解决方案就是通过代码展示中的操作,原因是因为form-data
提交上来的数据是另外一种格式,我们需要以数据流的方式去获取它,然后就可以将它里面的数据取出来了。到这里,第一个坑终于结束,但是第二个坑就此开始了 -
在第一个坑踩完后,本以为之后就可以顺风顺水,没想到第二个坑就来了,这次出现的问题是,在执行文件写出的时候报错
Method threw 'org.apache.commons.fileupload.MultipartStream$MalformedStreamException' exception.
具体错误就发生在文件写入的时候,这个问题我谷歌搜了好久,得到的答案就是:1.文件的边界格式读取有问题 2.可能电脑又加密软件啥的
后来实在解决不了,我就直接把这个文件写出给跳过了,然后第三个坑就开始了
-
第三个坑的错误与第二个坑如出一辙,都是文件方面的问题,在使用原项目的方式去遍历读取的时候,遍历到结束时会出现报错
org.apache.commons.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly
这个错误我当时也没有去解决,实在解决不了
后来,我想着有没有可能是它本来写的代码就有问题,于是,我就把他的ServletFileUpload
获取文件数据的方式去进行了修改,修改后发现,坑2和坑3都没了!!!后来经过简单是测试,调整,终于将需求完成。
代码展示
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置缓冲区大小
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建一个上床据
ServletFileUpload upload = new ServletFileUpload(factory);
//设置上传文件大小
upload.setFileSizeMax(1024*1024*50);
upload.setSizeMax(1024*1024*50);
//解决上传文件中文名称乱码
upload.setHeaderEncoding("UTF-8");
//定义一个map接收普通表单对象
Map<String, String> param = new HashMap<String, String>();
//定义一个List接受文件数据
List<FileItem> iter = new ArrayList<>();
//解析request对象,得到所有上传项,每一个fileItem相当于一个上传项(包括普通表单数据和文件数据)
List<FileItem> items = upload.parseRequest(req);
try {
//遍历解析出来的对象
for (FileItem fileItem : items) {
if (fileItem.isFormField()) {//如果是普通输入项数据
param.put(fileItem.getFieldName(), fileItem.getString("utf-8"));
}else {//如果是上传的文件数据
iter.add(fileItem);
}
}
} catch (Exception e) {
e.printStackTrace();
}
//将我们获取到的普通表单值赋值出来(之前我们存在了map里面)
String processID = param.get("ProcessID");
String serverPath = param.get("ServerPath");
String dateIn = param.get("dateIn");
String modifiedBy = param.get("modifiedBy");
String fileType = param.get("fileType");
//如果请求中存在文件
//如果不存在文件那么iter.get(0).getName()
if(!StringUtils.isEmpty(iter.get(0).getName())){
//开始文件操作
//创建文件数据集合的迭代器
Iterator<FileItem> iterator = iter.iterator();
//如果上传了多个文件,则会执行多次
while(iterator.hasNext()){
//获取迭代器中数据(存储的是我们传上来的文件数据)
FileItem fileItem = iterator.next();
//获取文件输入流
InputStream input = fileItem.getInputStream();
//获取文件名
fileName = fileItem.getName();
//后面的就是可以对文件输入流进行相关操作了
... ...
//以下省略
}
}
}
总结
- 在优化别人代码的时候,别人代码不一定正确
- 在写代码的时候要有写注释的好习惯
- 解决完bug后需要即使进行总结
- 问题解决不了不要着急,慢慢来