在上一篇文章《bboss mvc文件上传下载实战演练》 

http://yin-bp.iteye.com/blog/1130035 
中介绍了采用bboss mvc、aop/ioc、persistent组合完成文件上传、存储到数据库、从数据库中下载文件的基本功能,我们看到了如何通过MultipartHttpServletRequest获取上传文件,如何通过SQLExecutor/ConfigSQLExecutor中操作blob字段的api存储和读取文件的基本功能: 
FieldRowHandler(获取blob为文件的字段行处理器) 
NullRowHandler 

   本文作为上篇的进阶补充,介绍直接绑定MultipartFile对象或者MultipartFile数组到控制其方法参数或者po对象属性的案例。 
   对应的eclipse工程和运行demo可在本文的附件中下载: 
http://dl.iteye.com/topics/download/c7393bc6-b8ee-3dd5-b4b3-e969ea63dbc0 
   demo工程中包含了derby数据库文件目录database,部署到tomcat中运行之前需要修改/src/poolman.xml文件中dburl路径为相应物理路径的下的database/cimdb,编译后即可。 
  启动tomcat, 访问的地址还是: 
http://localhost:8080/bbossupload/upload/main.page 

   第一部分 本文的技术要点: 
1. 控制器方法参数绑定机制增加MultipartFile、MultipartFile[]类型绑定支持,可以和RequestParam注解一起使用,也可以直接使用(默认获取第一个input[file]域对应的附件),使用方法如下: 
public String uploadFileWithMultipartFile(@RequestParam(name="upload1")  MultipartFile file, 
ModelMap model) 
public String uploadFileWithMultipartFiles(@RequestParam(name="upload1")  MultipartFile[] files, 
ModelMap model) 

public String uploadFileWithMultipartFile( MultipartFile file, 
ModelMap model) 
public String uploadFileWithMultipartFiles(MultipartFile[] files, 
ModelMap model) 

2. PO对象属性数据绑定机制增加MultipartFile、MultipartFile[]类型绑定支持,可以和RequestParam注解一起使用,也可以直接与属性名称直接绑定,使用方法如下: 
public String uploadFileWithFileBean(FileBean files) 

FileBean是一个自定义的java bean,结构如下: 

Java代码  

  1. public class FileBean{  

  2.     private MultipartFile upload1;  

  3.     @RequestParam(name="upload1")  

  4.     private MultipartFile[] uploads;  

  5.     @RequestParam(name="upload1")  

  6.     private MultipartFile anupload;  

  7.     //省略属性的get/set方法  

  8. }     


3. 改进的SQLParams api,可以直接对MultipartFile对象存入clob或者blob列。 
sqlparams.addSQLParam("FILECONTENT", multipartfile,SQLParams.BLOBFILE); 

对于大字段的处理建议采用以下方法: 
sqlparams.addSQLParam("FILECONTENT", multipartfile,SQLParams.BLOBFILE);//直接传递MultipartFile对象进行插入 
sqlparams.addSQLParam("FILECONTENT", inputStream, size,SQLParams.BLOBFILE);//直接传递InputStream对象以及流大小Size属性进行插入 

一个完整的插入大字段的实例: 

Java代码  

  1. String sql = "";  

  2.         try {  

  3.             sql = "INSERT INTO filetable (FILENAME,FILECONTENT,fileid,FILESIZE) VALUES(#[filename],#[FILECONTENT],#[FILEID],#[FILESIZE])";  

  4.             SQLParams sqlparams = new SQLParams();  

  5.             sqlparams.addSQLParam("filename", filename, SQLParams.STRING);  

  6.             sqlparams.addSQLParam("FILECONTENT", inputStream, size,SQLParams.BLOBFILE);  

  7.             sqlparams.addSQLParam("FILEID", UUID.randomUUID().toString(),SQLParams.STRING);  

  8.             sqlparams.addSQLParam("FILESIZE", size,SQLParams.LONG);  

  9.             SQLExecutor.insertBean(sql, sqlparams);           

  10.               

  11.         } catch (Exception ex) {  

  12.             ex.printStackTrace();  

  13.             result = false;  

  14.             throw new Exception("上传附件关联临控指令布控信息附件失败:" + ex);  

  15.         } finally {  

  16.             if(inputStream != null){  

  17.                 inputStream.close();  

  18.             }  

  19.         }  

或者 

Java代码  

  1. public void uploadClobFile(MultipartFile file) throws Exception{   

  2.         String sql = "";  

  3.         try {  

  4.             sql = "INSERT INTO CLOBFILE (FILENAME,FILECONTENT,fileid,FILESIZE) VALUES(#[filename],#[FILECONTENT],#[FILEID],#[FILESIZE])";  

  5.             SQLParams sqlparams = new SQLParams();  

  6.             sqlparams.addSQLParam("filename", file.getOriginalFilename(), SQLParams.STRING);  

  7.             sqlparams.addSQLParam("FILECONTENT", file,SQLParams.CLOBFILE);  

  8.             sqlparams.addSQLParam("FILEID", UUID.randomUUID().toString(),SQLParams.STRING);  

  9.             sqlparams.addSQLParam("FILESIZE", file.getSize(),SQLParams.LONG);  

  10.             SQLExecutor.insertBean(sql, sqlparams);  

  11.         } catch (Exception ex) {  

  12.             throw new Exception("上传附件关联临控指令布控信息附件失败:" + ex);  

  13.         }  

  14.     }  

4. FieldRowHandler处理器,实现从blob/clob中获取单个字段文件对象的处理,其他类似类型数据也可以使用FieldRowHandler,使用示例如下: 

Java代码  

  1. public File getDownloadClobFile(String fileid) throws Exception{  

  2.         try{  

  3.             return SQLExecutor.queryTField(File.classnew FieldRowHandler<File>() { 

  4.                                                 @Override  

  5.                                                 public File handleField(  

  6.                                                         Record record)  

  7.                                                         throws Exception{  

  8.                                                     // 定义文件对象  

  9.                                                     File f = new File("d:/",record.getString("filename"));  

  10.                                                     // 如果文件已经存在则直接返回f  

  11.                                                     if (f.exists())  

  12.                                                         return f;  

  13.                                                     // 将blob中的文件内容存储到文件中  

  14.                                                     record.getFile("filecontent",f);  

  15.                                                     return f;  

  16.                                                 }  

  17.                                             },  

  18.                                             "select * from CLOBFILE where fileid=?",  

  19.                                             fileid);  

  20.         } catch (Exception e){  

  21.             throw e;  

  22.         }  

  23.     }  

第二部分 相关的实现细节 
由于上篇文章已经详细介绍了上传下载的代码详细情况,本文中只介绍MultipartFile控制器方法绑定和存储到数据库中部分实现以及下载方法实例,完整的代码请下载附件中的eclipse工程直接运行demo就可以了。 
1.控制器方法 

Java代码  

  1. public class UploadController{  

  2.     ...............  

  3.     /** 

  4.          * 直接使用MultipartHttpServletRequest 获取附件信息的方法 

  5.      * @param request 

  6.      * @param model 

  7.      * @param idNum 

  8.      * @param type 

  9.      * @param des 

  10.      * @param byid 

  11.      * @return 

  12.      */  

  13.     public String uploadFile(MultipartHttpServletRequest request,ModelMap model)

  14.         Iterator<String> fileNames = request.getFileNames();  

  15.         // 根据服务器的文件保存地址和原文件名创建目录文件全路径  

  16.         try{  

  17.             while (fileNames.hasNext()){  

  18.                 String name = fileNames.next();  

  19.                 MultipartFile[] files = request.getFiles(name);                

  20. //              file.transferTo(dest)  

  21.                 for(MultipartFile file:files){  

  22.                     String filename = file.getOriginalFilename();  

  23.                     if (filename != null && filename.trim().length() > 0){  

  24.                         uploadService.uploadFile(file.getInputStream(), file.getSize(), filename); 

  25.                     }  

  26.                 }  

  27.             }                

  28.         }catch (Exception ex){  

  29.             ex.printStackTrace();  

  30.         }  

  31.         return "path:ok";  

  32.     }  

  33.     /** 

  34.          * RequestParam注解和MultipartFile结合绑定参数方法,将参数upload1对应的附件直接以MultipartFile对象传入控制方法,简单又便捷,附件将被存储到derby数据库的blob字段中。 

  35.      * @param request 

  36.      * @param model 

  37.      * @param idNum 

  38.      * @param type 

  39.      * @param des 

  40.      * @param byid 

  41.      * @return 

  42.      */  

  43.     public String uploadFileWithMultipartFile(@RequestParam(name="upload1")  MultipartFile file,  

  44.             ModelMap model) {  

  45.         // 根据服务器的文件保存地址和原文件名创建目录文件全路径  

  46.         try {  

  47.             String filename = file.getOriginalFilename();  

  48.             if (filename != null && filename.trim().length() > 0){  

  49.                 uploadService.uploadFile(file.getInputStream(), file.getSize(), filename); 

  50.             }  

  51.         }catch (Exception ex){  

  52.             ex.printStackTrace();  

  53.         }  

  54.         return "path:ok";  

  55.     }  

  56.     /** 

  57.          * RequestParam注解和MultipartFile结合绑定参数方法,将参数upload1对应的附件直接以MultipartFile对象传入控制方法,简单又便捷,附件将被存储到derby数据库的clob字段中。 

  58.      * @param request 

  59.      * @param model 

  60.      * @param idNum 

  61.      * @param type 

  62.      * @param des 

  63.      * @param byid 

  64.      * @return 

  65.      */  

  66.     public String uploadFileClobWithMultipartFile(@RequestParam(name="upload1")  MultipartFile file,  

  67.             ModelMap model) {  

  68.         // 根据服务器的文件保存地址和原文件名创建目录文件全路径  

  69.         try{  

  70.             uploadService.uploadClobFile(file);  

  71.         }catch (Exception ex){  

  72.             ex.printStackTrace();  

  73.         }  

  74.         return "path:ok";  

  75.     }  

  76.     /** 

  77.          * RequestParam注解和MultipartFile[]结合绑定参数方法,将参数upload1(页面上有多个upload1 file input元素)对应的附件直接以MultipartFile[]对象传入控制方法,简单又便捷,附件将被存储到derby数据库的blob字段中。 

  78.      * @param request 

  79.      * @param model 

  80.      * @param idNum 

  81.      * @param type 

  82.      * @param des 

  83.      * @param byid 

  84.      * @return 

  85.      */  

  86.     public String uploadFileWithMultipartFiles(@RequestParam(name="upload1")  MultipartFile[] files,  

  87.             ModelMap model){  

  88.         // 根据服务器的文件保存地址和原文件名创建目录文件全路径  

  89.         try 

  90.             {     

  91. //              file.transferTo(dest)  

  92.                 for(MultipartFile file:files){  

  93.                     String filename = file.getOriginalFilename();  

  94.                     if (filename != null && filename.trim().length() > 0){  

  95.                         uploadService.uploadFile(file.getInputStream(), file.getSize(), filename);

  96.                     }  

  97.                 }  

  98.             }                

  99.         }catch (Exception ex) {  

  100.             ex.printStackTrace();  

  101.         }  

  102.         return "path:ok";  

  103.     }  

  104.       

  105.     /** 

  106.          * 本方法演示了po对象中绑定MultipartFile属性的功能。FileBean的结构如下: 

  107.          private MultipartFile upload1; 

  108.     @RequestParam(name="upload1") 

  109.     private MultipartFile[] uploads; 

  110.     @RequestParam(name="upload1") 

  111.     private MultipartFile anupload; 

  112.         上面的结构展示了不同属性绑定方式。 

  113.      * @param request 

  114.      * @param model 

  115.      * @param idNum 

  116.      * @param type 

  117.      * @param des 

  118.      * @param byid 

  119.      * @return 

  120.      */  

  121.     public String uploadFileWithFileBean(FileBean files,ModelMap model) {  

  122.         try 

  123.             //进行相应的处理  

  124.         } catch (Exception ex){  

  125.             ex.printStackTrace();  

  126.         }  

  127.         return "path:ok";  

  128.     } 

  129.     /** 

  130.      * 查询数据库的操作也只好放在控制器中处理 

  131.      * @param fileid 

  132.      * @param request 

  133.      * @param response 

  134.      * @throws Exception 

  135.      */  

  136.     public void downloadFileFromBlob(@RequestParam(name = "fileid") String fileid,  

  137.              HttpServletRequest request, HttpServletResponse response)throws Exception 

  138.         uploadService.downloadFileFromBlob(fileid, request, response);  

  139.     }  

  140.       

  141.     /** 

  142.      * 直接将blob对应的文件内容以相应的文件名响应到客户端,需要提供request和response对象 

  143.      * 这个方法比较特殊,因为derby数据库的blob字段必须在statement有效范围内才能使用,所以采用了空行处理器,来进行处理 

  144.      * 查询数据库的操作也只好放在控制器中处理 

  145.      * @param fileid 

  146.      * @param request 

  147.      * @param response 

  148.      * @throws Exception 

  149.      */  

  150.     public void downloadFileFromClob(@RequestParam(name = "fileid") String fileid,  

  151.              HttpServletRequest request, HttpServletResponse response)throws Exception

  152.         uploadService.downloadFileFromClob(fileid, request, response);  

  153.     }  

  154.   

  155.     /** 

  156.      * 将数据库中存储的文件内容转储到应用服务器文件目录中,然后将转储的文件下载,无需提供response和request对象 

  157.      *  

  158.      * @param fileid 

  159.      * @return 

  160.      * @throws Exception 

  161.      */  

  162.     public @ResponseBody File downloadFileFromFile(@RequestParam(name = "fileid") String fileid)throws Exception  {

  163.         return uploadService.getDownloadFile(fileid);  

  164.     }  

  165.     public @ResponseBody File downloadFileFromClobFile(@RequestParam(name = "fileid") String fileid)  

  166.     throws Exception {  

  167.         return uploadService.getDownloadClobFile(fileid);  

  168.     }  

  169.     ......  

2.持久层dao实现部分: 

Java代码  

  1. public class UpLoadDaoImpl implements UpLoadDao {        

  2.     @Override  

  3.     /** 

  4.      * CREATE 

  5.     TABLE CLOBFILE 

  6.     ( 

  7.         FILEID VARCHAR(100), 

  8.         FILENAME VARCHAR(100), 

  9.         FILESIZE BIGINT, 

  10.         FILECONTENT CLOB(2147483647) 

  11.     ) 

  12.      */  

  13.     public void uploadClobFile(MultipartFile file) throws Exception {            

  14.         String sql = "";  

  15.         try {  

  16.             sql = "INSERT INTO CLOBFILE (FILENAME,FILECONTENT,fileid,FILESIZE) VALUES(#[filename],#[FILECONTENT],#[FILEID],#[FILESIZE])";  

  17.             SQLParams sqlparams = new SQLParams();  

  18.             sqlparams.addSQLParam("filename", file.getOriginalFilename(), SQLParams.STRING);  

  19.             sqlparams.addSQLParam("FILECONTENT", file,SQLParams.CLOBFILE);  

  20.             sqlparams.addSQLParam("FILEID", UUID.randomUUID().toString(),SQLParams.STRING);  

  21.             sqlparams.addSQLParam("FILESIZE", file.getSize(),SQLParams.LONG);  

  22.             SQLExecutor.insertBean(sql, sqlparams);   

  23.         } catch (Exception ex) {   

  24.             throw new Exception("上传附件关联临控指令布控信息附件失败:" + ex);  

  25.         }   

  26.     }  

  27.       

  28.     /** 

  29.      * 上传附件 

  30.      * @param inputStream 

  31.      * @param filename 

  32.      * @return 

  33.      * @throws Exception 

  34.      */  

  35.     public boolean uploadFile(InputStream inputStream,long size, String filename) throws Exception {  

  36.         boolean result = true;  

  37.         String sql = "";  

  38.         try {  

  39.             sql = "INSERT INTO filetable (FILENAME,FILECONTENT,fileid,FILESIZE) VALUES(#[filename],#[FILECONTENT],#[FILEID],#[FILESIZE])";  

  40.             SQLParams sqlparams = new SQLParams();  

  41.             sqlparams.addSQLParam("filename", filename, SQLParams.STRING);  

  42.             sqlparams.addSQLParam("FILECONTENT", inputStream, size,SQLParams.BLOBFILE);  

  43.             sqlparams.addSQLParam("FILEID", UUID.randomUUID().toString(),SQLParams.STRING);  

  44.             sqlparams.addSQLParam("FILESIZE", size,SQLParams.LONG);  

  45.             SQLExecutor.insertBean(sql, sqlparams);           

  46.               

  47.         } catch (Exception ex) {  

  48.             ex.printStackTrace();  

  49.             result = false;  

  50.             throw new Exception("上传附件关联临控指令布控信息附件失败:" + ex);  

  51.         } finally {  

  52.             if(inputStream != null){  

  53.                 inputStream.close();  

  54.             }  

  55.         }  

  56.         return result;  

  57.     }  

  58.       

  59.     public File getDownloadFile(String fileid) throws Exception{  

  60.         try{  

  61.             return SQLExecutor.queryTField(File.classnew FieldRowHandler<File>() {  

  62.                                             @Override  

  63.                                             public File handleField(Record record)throws Exception{

  64.                                             // 定义文件对象  

  65.                                              File f = new File("d:/",record.getString("filename"));  

  66.                                              // 如果文件已经存在则直接返回f  

  67.                                              if (f.exists())  

  68.                                                   return f;  

  69.                                              // 将blob中的文件内容存储到文件中  

  70.                                              record.getFile("filecontent",f);  

  71.                                               return f;  

  72.                                            }  

  73.                                     },"select * from filetable where fileid=?" fileid);  

  74.         } catch (Exception e) {  

  75.             throw e;  

  76.         }  

  77.     }  

  78.       

  79.     public File getDownloadClobFile(String fileid) throws Exception{  

  80.         try{  

  81.             return SQLExecutor.queryTField(File.class,new FieldRowHandler<File>() {  

  82.                                      @Override  

  83.                                      public File handleField(Record record)throws Exception{                                                   // 定义文件对象  

  84.                                             File f = new File("d:/",record.getString("filename"));  

  85.                                                     // 如果文件已经存在则直接返回f  

  86.                                                     if (f.exists())  

  87.                                                         return f;  

  88.                                                     // 将blob中的文件内容存储到文件中  

  89.                                                     record.getFile("filecontent",f);  

  90.                                                     return f;  

  91.                                                 }  

  92.                                             },"select * from CLOBFILE where fileid=?", fileid);  

  93.         }catch (Exception e) {  

  94.             throw e;  

  95.         }  

  96.     }  

  97.   

  98.     @Override  

  99.     public void deletefiles() throws Exception {    

  100.         SQLExecutor.delete("delete from filetable ");     

  101.         SQLExecutor.delete("delete from CLOBFILE ");      

  102.     }    

  103.     @Override  

  104.     public List<HashMap> queryfiles() throws Exception 

  105.         return SQLExecutor.queryList(HashMap.class"select FILENAME,fileid,FILESIZE from filetable"); 

  106.     }  

  107.     @Override  

  108.     public List<HashMap> queryclobfiles()throws Exception {    

  109.         return SQLExecutor.queryList(HashMap.class"select FILENAME,fileid,FILESIZE from CLOBFILE"); 

  110.     }  

  111.   

  112.     @Override  

  113.     public void downloadFileFromBlob(String fileid, final HttpServletRequest request,  

  114.             final HttpServletResponse response) throws Exception {    

  115.         try {  

  116.             SQLExecutor.queryByNullRowHandler(new NullRowHandler() {  

  117.                 @Override  

  118.                 public void handleRow(Record record) throws Exception {    

  119.                     StringUtil.sendFile(request, response, record  

  120.                             .getString("filename"), record  

  121.                             .getBlob("filecontent"));  

  122.                 }  

  123.             }, "select * from filetable where fileid=?", fileid);  

  124.         }catch (Exception e){  

  125.             throw e;  

  126.         }

  127.     }  

  128.     @Override  

  129.     public void downloadFileFromClob(String fileid, final HttpServletRequest request,  

  130.             final HttpServletResponse response) throws Exception  {  

  131.         try {  

  132.             SQLExecutor.queryByNullRowHandler(new NullRowHandler() {  

  133.                 @Override  

  134.                 public void handleRow(Record record) throws Exception{  

  135.                     StringUtil.sendFile(request, response, record  

  136.                             .getString("filename"), record  

  137.                             .getClob("filecontent"));  

  138.                 }  

  139.             }, "select * from CLOBFILE where fileid=?", fileid);  

  140.         }catch (Exception e){  

  141.             throw e;  

  142.         }            

  143.     }  

  144. }  



代码都很简单,也非常容易理解,这里不做过多的解释。有问题可以留言讨论,也可以加入群组: 
21220580 
3625720 
154752521 
官方网站: 
http://www.bbossgroups.com/