您的位置:首页 > 其它

How to read a text file attached to a Lotus Notes Document WITHOUT detaching it?

2012-04-23 22:30 204 查看
One of the biggest problems when dealing with file attachments in Lotus Notes documents is that you can't detach the files on the server. This is due to a setting on the Public Names & Address Book on the server. Usually the server's administrator will not allow the use of unrestricted agents so the agent's will not touch any file on the server (which is a good idea).

But in some cases you will need to detach a file on the server to work with. If the administrator won't put you in the group who are authorized to use unrestricted agents, or not willing to sign the agent then you will need to find a workaround. In some cases if you are using a server which is hosted by a 3rd party you will not always have the rights to use unrestricted Lotus Script or Java agents.

While looking for a solution on the web, I have tumbled over several articles where people are trying to do the same thing, for example this article on Techtarget.com: Can you use LotusScript to read a text file attached to a Notes doc?. One idea to get started is to check this excellent article from Jake Howlett on Codestore.net: Generating File Attachments in Agents Without Unrestricted Rights.

I wanted to have a simpler solution and also have a better understanding of what has to be done, so I'm sharing this easy to understand workaround, it is simply for the Lotus Notes developers out there to get an idea on how to do it.

First, there is no way to read a file attached to a Lotus Notes Document using only LotusScript, you can get the attachments filename, delete or add attachment but not actually work with the attached file without detaching it. The solution is to get some help with a Java agent that allows us to do a lot more stuff on Lotus Notes & Domino.

We are going to use two Lotus agents to do that, the first one will be a LotusScript agent to get the data from the Notes Document and pass it to the Java agent which will read the file attached and return a string back to the LotusScript agent.

The first problem you will face by using two different agent's is to find a way to pass some data from one agent to the other, you could write the parameters you need in the Lotus Notes document but then you will face some other problems, for example the document date will be modified and the document will have to be replicated over all the replica's. So when running the LotusScript agent, we will create a temporary Parameter document and write all the parameter needed in some fields.

You will find below the LotusScript agent listing, in this example we want to get the data of the attached file name "test0.txt". This agent will create a parameter document and put the Document ID in a field, as well as the name of the file attachment to read.

Then we will pass this document to the Java agent and it will write the

Listing 1: LotusScript Agent: "ReadAttachmentLS"

Sub Initialize
Dim s As New NotesSession
Dim db As NotesDatabase
Dim workspace As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = workspace.CurrentDocument
Dim doc As NotesDocument
Set doc = uidoc.Document
Dim agent As NotesAgent
Set db = s.CurrentDatabase

'In this example we will read the data of a file attachment named
'"test0.txt"
'This is done by calling a Java agent, which will read the attachment
'WITHOUT detaching
'the file to the hard disk
Dim theFileAttachmentToRead As String
theFileAttachmentToRead = "test0.txt"

'Populate the parameters to be used by the Java agent
'As described here:
'http://www.ibm.com/developerworks/lotus/library/ls-Run_and_RunOnServer/
'index.html
'It is off course better to create a parameter document as described in the
'above URL, like this, for example,
'the modification date won't be modified

'Create document that will be used for parameter passing
Dim parameterDoc As NotesDocument
Set parameterDoc = db.CreateDocument

'Add the field that will contain the value filename & Universal ID
Dim item As NotesItem
Set item = parameterDoc.AppendItemValue("Filename", theFileAttachmentToRead)
Set item = parameterDoc.AppendItemValue("UniversalID", doc.UniversalID)

'Save the document
Call parameterDoc.save(True, False)

'Set the parameter value of the parameter document
Dim paramid As String
paramid = parameterDoc.Noteid

Set agent = db.GetAgent("ReadAttachmentJava")
'Start agent and pass note ID of document
'Use agent.RunOnServer(paramid) to run the agent on the server
If agent.Run(paramid) = 0 Then
Print "Agent ran - Success"
Else
Print "Agent did not run - Failure"
End If

'Delete in-memory document. This is necessary because we need to reload
'the document in order to get the latest data which the Java Agent has
'written into the parameter document
Delete parameterDoc

'Get the result from the parameter document (the data from the file
'attachment)
Dim theResult As String
Set parameterDoc = db.GetDocumentByID(paramid)
theResult = parameterDoc.Result(0)

'Do whatever you need with the data
'Your code goes here
Print "parameterDoc: Result=" + theResult

'When finished delete the temporary parameter document
Call parameterDoc.RemovePermanently(True)
End Sub


Now we need to create a Java agent, which will read the parameter document to get the document ID and the name of the attachment to read from, we will use standard Java IO stream function to read the file, once it is read, we write the content in a result field in the previously passed parameter document.

Listing 2: Java Agent: "ReadAttachmentJava"

import lotus.domino.*;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class JavaAgent extends AgentBase {
public void NotesMain() {
try{
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
Database db = agentContext.getCurrentDatabase();
Agent agent = agentContext.getCurrentAgent();

//Get document used for passing data
Document paramDoc = db.getDocumentByID(agent.getParameterDocID());

//Get the Universal ID and the Document where the attachment
//is located
String UniversalID = paramDoc.getItemValueString("UniversalID");
Document doc = db.getDocumentByUNID(UniversalID);

//Get the attachment filename from the parameter document
String filename = paramDoc.getItemValueString("Filename");
EmbeddedObject obj = doc.getAttachment(filename);

String theJavaResult = "";
if (obj != null) {
paramDoc.replaceItemValue("theJavaResult", "Found " +
obj.getName());
}

java.io.InputStream is = obj.getInputStream();
String theResult = "";
if (is != null) {
//read the stream of the file
theResult = convertStreamToString(is);
} else
paramDoc.replaceItemValue("theJavaResult", "No
Attachment InputSource!");
//Destroy object
obj.recycle();

//Save the parameter Doc with the result
//put the result into a temporary field
paramDoc.replaceItemValue("Result", theResult);
paramDoc.save();
}
//Catch if something wrong happens from Notes side like,
//Database/view failed to open or invalid formula etc
catch(NotesException e) {System.out.println(e.id + " " + e.text);}
//Usual Java Exception class
catch(Exception e) { e.printStackTrace(); }
}

public static String convertStreamToString(InputStream is) throws
Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
return sb.toString();
}
}


Once the Java agent has finished, we return to the LotusScript agent and read the result field from the parameter document. There is the place where you write the code you want your agent to do with the data. Don't forget to delete the parameter document if you don't need it anymore.

So, I hope this will give you a simple idea on how you can read file attachments without detaching them and how to pass parameters from one agent to another.

Some of you will ask, why not use a Java Library instead of a Java agent? Well because at this time, LS2J (IBM's LotusScript To Java), won't allow you to have access to the documents or uidocuments directly, you will need to use a Java agent in order to get the NoteID from LotusScript.

This code has been tested on Lotus Domino & Notes version > 8.x.

Best regards,
Adel Habib
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: