登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

人 生 海 海

常常我豁出去拚了命走过却没有痕迹,常常我闭上眼睛听到了海的呼吸是你

 
 
 

日志

 
 

Domino中通过servlet上传附件  

2009-11-25 14:18:06|  分类: 技术交流 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

    在B/S开发模式下,Domino表单设计中自带了一个附件上传控件,通过它,可以很方便地将附件上传至文档。这种方式的弊端在于对于某些附件特别多的数据库,容易造成数据库过于庞大,这种情况下,将附件与文档分开存储是比较通用的解决方法。Domino从R5开始就支持servlet了,以下说明摘自IBM官网。

    Servlet特点以及与Agent的区别:

    Servlet是运行在服务器上的Java程序,提供类似于CGI应用和Domino Agent的功能。Servlet的主要优点是只装载入内存一次,而Agent和CGI程序是每次调用时都需装载入内存。Sservlet一次装载入内存后,以后所有调用都使用该实例。例如,针对连接数据库的任务,您可以选择Servlet来保持一个永久连接传输数据,提高运行效率。

    尽管Agent和Servlet提供类似功能,但它们的实现差别很大。Agent存在于Domino数据库而Servlet在文件系统下。这立即带来了两个问题:分布和安全。Agent可以充分利用它所在的数据库,因此,可通过复制分布到其它服务器。同样,Domino安全模式控制Agent的访问。相反,Servlet存在于文件系统,因此由服务器、文件和目录安全来控制Servlet的访问。Servlet缺省是以服务器安全权限来运行,但也可以某一特定Internet用户名字和口令来运行。最后,除非使用WinNT目录复制,否则您必须拷贝或安装Servlet到其它需要的服务器。

    现在来实践下,利用一个开源的java附件上传工具:commons-fileupload,编写一个servlet实现将客户机选择的附件上传至Domino服务器磁盘的功能,以达到文档与附件分开存储的目的。

    一、要使用Domino服务器能够运行管理servlet,必须先对服务器进行servlet管理设置。打开服务器文档切换至"Internet Protocol"->"Domino Web Engine"选项,如图:

Domino中通过servlet上传附件 - Kenny - 人 生 海 海

    基本保持默认设置,其中Servlet file extensions是指servlet扩展名,例如可以通过url:http://yourserver/servlet/servletname或者http://yourserver/servlet/servletname?svl来访问servlet。另外url也对servlet名的大小写敏感。

    二、引入所用的jar包,配置notes.ini的JavaUserClasses参数。servlet用commons-fileupload上载附件,所以要把commons-fileupload.jar和javax.servlet.jar放到服务器上,当然Notes.jar也是必须的。另外配置JavaUserClasses可以用通配符*,例如把所有的jar都放在服务器安装目录的Lotus\Domino\jvm\lib\ext下,那么就可以直接用JavaUserClasses=D:Program Files\IBM\Lotus\Domino\jvm\lib\ext\*;而无需一个一个jar添加。且后续若有新的jar加入,只需将jar文件放到这个目录下,然后重启下http服务,可以生效了。

    三、设计表单。

Domino中通过servlet上传附件 - Kenny - 人 生 海 海

    这里在单元格里放了一个form,注意这里是标签顺序是</form><form>,若用常规的<form></form>表单将无法提交。因为一个form只能有一个submit生效,这里用了一个button实现上传,用submit实现删除。form默认的method是get,对应servlet里面的doGet方法,用来处理删除请求。上传的时候method置为post,对应servlet里面的doPost方法,用来处理上传的请求,上传按钮的onclick事件为:

Domino中通过servlet上传附件 - Kenny - 人 生 海 海

    由于用submit提交form后,servlet里面request只能获取form上input元素的值,而用button提交form后,servlet里面request只能获取url传递的参数,因此,这里这里所需要的参数既要体现在input元素上也要体现在url参数中。本例中所需的4个参数是:

    svr:服务器的简称,用公式@Name([CN];@ServerName)获得

    db:数据库路径,用公式@WebDbName获得

    uid:当前文档的ID,用公式@DocumentUniqueID获得

    filenameitem:用来存放附件名称的多值域

    有了svr、db、uid这3个参数,就可以在servlet中定位到当前打开的文档,在servlet处理上传或删除后将页面重定向回原始打开的页面。另外还需要在表单上创建一个多值域files,用来存放上传的附件名称,域名作为filenameitem参数的值传递给servlet。

    最后用一个内置HTML的计算文本来将附件名显示为链接:

Domino中通过servlet上传附件 - Kenny - 人 生 海 海

    四、编写severlet。由于Domino Designer并不支持servlet编写,所以只能借助其它的IDE来生成servlet,这里用eclipse来编写一个FileUpload类,特别说明的是,这个类一定不能用package指明路径,一定要放在default package下,否则在Domino下运行会报错。这个类的结构如下:

Domino中通过servlet上传附件 - Kenny - 人 生 海 海

    需要用到的包是commons-fileupload.jar、javax.servlet.jar和Notes.jar,下面是主要的方法说明。

    servlet初始化方法init():

 public void init() throws ServletException {
  dir = "D:\Program Files\IBM\Lotus\Domino\data\domino\icons\attachment";  //(1)
  domain = "";  //(2)
  ss = null;
  db = null;
  doc = null;
  item = null;
 }

    删除附件doGet():

 public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  response.setContentType("text/html");
  getParameters(request);  //(3)
  String atts[] = request.getParameterValues("atts");  //(4)
        try{
         NotesThread.sinitThread();
         ss = NotesFactory.createSession();
         db = ss.getDatabase(svrname, dbname);
         doc = db.getDocumentByUNID(uid);
         item = doc.getFirstItem(filenameitem);  //(5)
      for(int i = 0;i<atts.length;i++){
       String att = new String(atts[i].getBytes("ISO-8859-1"),"UTF-8");  //(6)
       File del = new File(dir + "\\" + att);
       if(del.delete()){  //(7)
        Vector v = item.getValues();
        for(int k = 0;k < v.size();k++){
         String f = (String)v.get(k);
         if(f.equals(att)){
          v.removeElementAt(k);  //(7)
          break;
         }
        }
        item.setValues(v);
       }
      }
         doc.save(true, false);
         url = "http://" + "localhost" + domain + "/"  + dbname + "/0/" + doc.getUniversalID() + "?EditDocument";
         recycleDominoObj();  //(8)
        }catch(NotesException e){
         System.out.println("Servlet FileUpload method doGet domino object error:" + e.getMessage());
         e.printStackTrace();
        }finally{
         NotesThread.stermThread();
        }
        response.sendRedirect(url);  //(9)
 }

    上传附件doPost():

 public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {
  response.setContentType("text/html");
  getParameters(request);
        try{
         NotesThread.sinitThread();
         Session ss = NotesFactory.createSession();
         Database db = ss.getDatabase(svrname, dbname);
         Document doc = db.getDocumentByUNID(uid);
         Item item = doc.getFirstItem(filenameitem);
         List filenames = uploadFiles(request);  //(10)
         for(Iterator it = filenames.iterator();it.hasNext();){
          item.appendToTextList((String)it.next());  //(11)
         }
         doc.save(true, false);
         url = "http://" + "localhost" + domain + "/"  + dbname + "/0/" + doc.getUniversalID() + "?EditDocument";
         recycleDominoObj();
        }catch(NotesException e){
         System.out.println("Servlet FileUpload method doPost domino object error:" + e.getMessage());
         e.printStackTrace();
        }finally{
         NotesThread.stermThread();
        }
        response.sendRedirect(url);
 }

    获取request中所需的参数getParameters():

 private void getParameters(HttpServletRequest request){
  svrname = request.getParameter("svr");
  dbname = request.getParameter("db");
  uid = request.getParameter("uid");
  filenameitem = request.getParameter("filenameitem");
 }

    回收Domino对象recycleDominoObj():

 private void recycleDominoObj(){
  try {
   if(item != null) item.recycle();
      if(doc != null) doc.recycle();
      if(db != null) db.recycle();
      if(ss != null) ss.recycle();
  } catch (NotesException e) {
   System.out.println("Recycle domino object error:" + e.getMessage());
   e.printStackTrace();
  }
 }

    实现附件上传uploadFiles:

 private List uploadFiles(HttpServletRequest request){
  List<String> filenames = new ArrayList<String>();
  Date now = new Date();
  SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");  //(12)
  String nowString = format.format(now);
  try{
   DiskFileUpload fu = new DiskFileUpload();
            fu.setSizeMax(1024 * 1024 * 20);  //(13)
            fu.setSizeThreshold(1024 * 1024 * 5);  //(14)
            fu.setRepositoryPath(System.getProperty("java.io.tmpdir")); //(15)
            fu.setHeaderEncoding("UTF-8");
            try {
             List files = fu.parseRequest(request);
             for(Iterator it = files.iterator();it.hasNext();){
              FileItem file = (FileItem)it.next();
              if(!file.isFormField() && null != file.getName() && 0 != file.getName().trim().length()) {
               String clientPath = file.getName();
               String fileName = new File(clientPath).getName();
               fileName = nowString + "." + fileName;
                        File destDir = new File(dir);
                        File load = new File(destDir, fileName);
                        file.write(load);
                        filenames.add(fileName);
              }
             }
            }catch(Exception e){
             System.out.println("Servlet FileUpload method uploadFiles upload file error:" + e.getMessage());
             e.printStackTrace();
            }
  }catch(Exception e){
   System.out.println("Servlet FileUpload.uploadFiles:" + e.toString());
   e.printStackTrace();
  }
  return filenames;
 }

    (1)附件上传到Domino服务器上的绝对路径,这里之所以要用Domino数据目录下的icons文件夹,是因为该路径在Domino映射管理下,可以直接通过url访问到此路径下的文件。

    (2)初始化域名,例如.IBM.COM.CN,本例是在本机测试,故初始为空。

    (3)获取form或者url传递的参数。

    (4)获取checkbox选中的附件。

    (5)得到文档上存储附件名称列表的域。

    (6)解决附件名称带中文会乱码的问题。

    (7)删除文件,并将文件名从存储附件名称的域里剔除。

    (8)回收Domino对象,这是必需的。

    (9)将url重定向回打开的文档。

    (10)上传附件,并返回附件的名称列表。

    (11)将附件名称添加到文档上存储附件名称的域里。

    (12)附件保存到服务器磁盘前,在文件名前添加一个时间参数,防止覆盖同名文件。

    (13)上传附件的最大值。

    (14)分配的内存大小。

    (15)上传的附件大小大于分配的内存大小时的临时文件存储路径。

    五、发布servlet。将编译好的servlet文件FileUpload.class放到服务器上配置的servlet路径,本例的路径为D:\Program Files\IBM\Lotus\Domino\data\domino\servlet,然后重启http服务。另外,后续若修改这个文件,替换后仍然需要重启http服务才能生效。

    六、测试。

    上传后:

Domino中通过servlet上传附件 - Kenny - 人 生 海 海

    未选中删除:

Domino中通过servlet上传附件 - Kenny - 人 生 海 海

    删除后:

Domino中通过servlet上传附件 - Kenny - 人 生 海 海

    最后需要说明的是,新建未保存的文档不能通过Database对象的getDocumentByUNID方法获得,因此提交form到servlet后无法重定向回当前文档,所以未保存的文档需要保存后才可以用这个方法上传文件。本例在Domino R8.5下测试通过。

  评论这张
 
阅读(1835)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018