使用Struts2上传文件过程中遇到的一个问题
背景:项目中涉及到表单数据提交,其中还包含有图片。
关于如何保存图片,我一开始有两种思路:
- 将图片转换成二进制字节流,然后保存到数据表当中(项目中用的是Oracle数据库,保存二进制字节流的那个字段定义成blob类型就可以了)。
- 将图片上传到服务器,然后数据表中保存的是文件名(如 eakon.jpg)。只保存文件名是出于这样的考虑:因为现在只给我们项目组分配了一台服务器,以后图片可能要放到专门的文件服务器上,如果现在把路径也保存到数据表当中去的话我怕到时候万一项目的部署方式一改就会牵扯到很多东西,所以就直接保存个文件名。如果要将图片展示在前台页面上的话,就在业务层拼接一下绝对路径/相对路径。
一开始我选择了第一种方式,即将图片转换成二进制字节流编码然后存到数据表的大数据字段当中去,后来也是考虑到项目后期部署的问题,以及图片展示的问题--------假如要将图片展现在前台页面,首先要将该图片对应的存储在数据表中二进制数据取出来,取出来之后还要涉及到一系列的数据格式转换问题。因为不能直接将二进制数据直接传到jsp页面,在此之前还要对其进行处理。觉得比较麻烦,所以后来选择了第二种方式来对图片进行上传的操作。
一开始在Action中老是获取不到上传的文件,一时不知道是什么原因。后来把图片上传涉及到的代码重新检查了一下,然后修改了一下拦截器又能上传图片了,暂时没找到原因在哪里。先总结一下在上传文件(这里只针对图片文件,其他文件可能还涉及到设置编码字符集的问题,以后遇到了再总结)的过程中需要注意的地方。
我这里用的是jsp表单提交的方式,没有使用Ajax
jsp页面里面需要注意的地方:
- 在form标签中 enctype 属性应该设置为 "multipart/from-data"
- 文件域的name和后台Action中接收文件的变量名要一致
- 提交按钮应为 submit 标签
Struts2配置时需要注意的地方
一定要配置一个属性指定文件存放的临时目录。如果是使用xml文件进行配置的话,需在Struts.xml文件中进行如下配置:
关于拦截器
我是在action标签中嵌了一个拦截器,最好是用<interceptor-ref name="" class="" ></interceptor-ref>的方式定义拦截器然后添加到拦截器栈里面去,需要用的时候再到action里面引用比较好,可以做到代码复用
关于处理文件上传的Action
- 需要定义一个File类型的变量来接收从前台传过来的文件(其实文件从前台传过来之后,会保存在我们定义的临时存放目录里面,然后在完成了Action中对应的方法之后系统会把临时目录里面的临时文件给清除)。
- 比如说 File 类型的变量名字为 File eakon。我们可以再定义三个String类型的变量,分别为 title, eakonFileName, eakonContentType。可以获取到 文件标题、文件名以及文件的类型(必须引入上面的两个jar包,并且按照 文件类型变量名+FileName, 文件类型变量名+ContentType才能获取到文件名以及文件类型)。但是要记得生成对应的get/set方法。
只要注意以上几点,上传图片的功能基本就能实现了(有一些具体的业务代码就不贴了,只贴一个主要的函数)。
在前台页面输入需要提交的信息:
企业营业执照扫描件为需要上传的图片,上传之后会使用企业营业执照编号作为文件名
点击保存之后触发对应的action,在调用对应的Action中的函数之前,首先会被拦截器拦截,判断上传的文件类型以及大小是否符合定义的要求,如果符合,那就进入对应的method进行处理。
下面这个函数的功能就是将临时目录下面的文件里面的内容复制到指定路径下的文件当中
@Override
/*将文件保存到路径为fileName的地方,其中fileName包括了文件名以及路径
* @param file 从前台获取到的文件
* @param filePath 路径+文件名
* */
private static final int BUFFER_SIZE = 16*1024;//文件缓冲区大小
public void copyAndSaveFile(File file,String filePath) throws IOException{
File dst = new File(filePath);
InputStream in = null;
OutputStream out = null;
try{
in = new BufferedInputStream(new FileInputStream(file),BUFFER_SIZE);
out = new BufferedOutputStream(new FileOutputStream(dst),BUFFER_SIZE);
byte[] buffer = new byte[BUFFER_SIZE];
int len = 0;
while( (len=in.read(buffer)) > 0){
out.write(buffer, 0, len);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(null != in){
try{
out.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
经过上述处理,文件已经保存到了目标文件夹下面:
文件已经保存到了指定目录在数据表中的对应字段,只保存了文件名:
数据表对应字段保存的是文件名(不带路径)如果需要将图片在前台页面显示出来,只需取出对应的文件名,然后加上访问路径传到前台 img 标签的src属性即可