zoukankan      html  css  js  c++  java
  • Domino中通过servlet上传附件

    在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 - 人 生 海 海

        删除后:

     

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

  • 相关阅读:
    Subsets
    Search a 2D Matrix II
    Search a 2D Matrix
    Search Insert Position
    Search for a Range
    Sort Colors
    Sort List
    语音笔记04-3 TEHO,COR
    语音笔记04-2 拨号规则
    语音笔记04-1 CME实验
  • 原文地址:https://www.cnblogs.com/hannover/p/1839794.html
Copyright © 2011-2022 走看看