Friday, May 19, 2006

Using LotusScript to import an image resource

A few years back I wrote some code and co-authored an article on using the Java and DXL Toolkit to import image resources into the domino design. I figured as my first blog entry I'd write about the same subject utilizing the latest LotusScript APIs in release 6x to import an image resource into a Lotus Domino design...

We start with a simple notes form with a single file upload control and a submit button that invokes an agent on submit.

The agent code below handles importing the imageSub Initialize
On Error Goto MyErr

Dim s As New NotesSession
Dim db As NotesDatabase
Dim col As NotesDocumentCollection
Dim doc As NotesDocument
Dim fileNames As Variant Dim item As NotesRichTextItem
Dim bean As FileBean
Dim factory As New FileBeanFactory()
Dim resource As ImageResource

Set db = s.CurrentDatabase
Set doc = s.DocumentContext

'creates the object collection of FileBeans.
Call factory.createFileBeans(doc)
'now get the bean based on one of the file names in the doc
fileNames = Evaluate("@AttachmentNames",doc)
'get the FileBean object from the factory using a file name as the key
Set bean = factory.getFileBean(fileNames(0))
'set the resource to a new image resource based on FileBean
Set resource = New ImageResource(bean)
'save the image resource to database (note can be any database)
Call resource.saveToDatabase(db)

Exit Sub

Dim errBody As String
errBody =Lsi_info(2) & " " & Str(Err) & ": " & Error$ & " on line: " & Erl()
Print errBody

Exit Sub

End Sub

In the above agent you will notice that I've created three custom classes to facilitate the importation of the image resource:

  • FileBean (temporary data store for a single attachment containing the base64 encoded file data)
  • FileBeanFactory (factory class that creates a FileBean per attached file in the document using DXLExporter and SAX parser to create a collection of FileBean(s))
  • ImageResource (class that takes the bean and does the import using the DXLImporter to passed in database)

In a nutshell this is pretty much it. There is a BeanFactoryHelper class that is wrapped by FileBeanFactory. If you are interested in seeing how the FileBean is built using the SAX parser look there. There is also a handy collections object I've built and use in most of my apps. It is sort of a hybrid between a HashMap and an ArrayList.... containing methods to get object handles via index, and string keys along with some enumeration helpers like getFirst, getNext, getNth(i) etc... To try out the app download .zip and extract the .nsf to you domino server. Once setup on domino launch the Upload_Image?OpenForm url command on your development domino server using http://yourhost/ImageResourceImport.nsf/Upload_Image?OpenForm



Mac Guidera said...

Great stuff! I always thought that your DXL Import was way ahead of its time. I'm sure you've got more.
Keep it coming!

Mikkel Heisterberg said...

Cool - I don't know if you know but I wrote some code (Helping out a fellow blogger getting the actual bytes of an image resource - a lesson in the intricacies of DXL representation) to export an image resource from a database using DXL. Combining the two efforts means that we have code to do a roundtrip. Nice.

Anatoly said...

Is it possible to DELETE particular (by name for example) image resource ?

Mark Ambler said...

Since an image resource is stored in a notes doc.. you can use noteId collection to get a handle (see below)

Sub Initialize
Dim s As New NotesSession
Dim db As NotesDatabase
Dim nc As NotesNoteCollection
Dim noteId As String
Dim docImage As NotesDocument
Dim item As NotesItem
Dim img As String

Set db=s.CurrentDatabase
Set nc = db.CreateNoteCollection(False)
Call nc.SelectAllFormatElements(False)
nc.SelectImageResources = True
Call nc.BuildCollection

noteId = nc.GetFirstNoteId
Do While Not noteId = ""
Set docImage = db.GetDocumentByID(noteId)
img= docImage.GetItemValue("$TITLE")(0)
If img="deleteme.gif" Then
Call docImage.Remove(True)
End If
noteId = nc.GetNextNoteId(noteId)

End Sub

Jens Bruntt said...

Very interesting. Just what I need atually.
What Domino version is this for? I have a feeling that it's R7 only.

Mark Ambler said...

The import for the image resource should work w/ 6x (I think my original build for it was 6.5x)... as the DXLImporter/DXLExporter LS classes were introduced in 6x.. same w/ the NotesSAXParser. Let me know if you encounter any issues w/ it in 6x.... and thanks for the comment...



Joacim said...

Great Stuff!

Worked perfectly in my R7.02 test environment! But when I tried to implement it in production (R6.51) i get an error message:

"Missing namespace for root element DXL importer operation failed"

Any ideas?



Mark Ambler said...

Is it ND 7x server w/ 6.5x client? My first guess would be to check the xmlschemas folder to see if the .dtd referenced in the DXL is there. You may want to try and copy the missing .dtds over from 7x into 6.5x xmlschemas folder to see if it works.

Ayisha said...

Nice and knowledgeable gifts for everyone-
Books and references

luisito77 said...

I have been looking for a solution to upload/delete image resources all over the web, your solution appears to be the easiest and shorten of the solutions i have found, but the application you mentioned we can download to try this solution is not working, how can i get it, thanks in advance... regards. said...

I am receiving this error message when I use the Submit button on the web - 'You are not authorized to perform that operation DXL importer operation failed'
version 7.02 I have manager access to the database