Showing posts with label LS2J. Show all posts
Showing posts with label LS2J. Show all posts

Wednesday, January 20, 2021

How to post attachments using form to agent

I have a form with some text fields and I also needed to send attachments within same form.

Form is printed by agent and is processed by another agent written in LotusScript.

I spent some time working on solution and here it is.

The idea is to convert selected files to base64 on client side and then post data on submission and agent that process submission will conver base64 to file.

Here is a form, note that we run some logic when files are added

<form name="formName" method="post" action="agentName?openagent">
<input name="title" value="xxx">
<input type="file" name="files" multiple onchange="toBase64()">
</form>

Here is how we convert selected files to base64 and how we results as text fields to form (JS is not optimal, it can be done without jQuery)

function toBase64() {
  var files = document.querySelector('input[type=file]').files;

  var form = $("form");
  form.find("input[name^='filebase64']").remove(); // replace

  function readAndSave(file, index) {
    var reader = new FileReader();
	
    reader.addEventListener("load", function() {
      form.append("");
      form.append("");
    }, false);

    reader.readAsDataURL(file);
  }

  if (files) {
    [].forEach.call(files, readAndSave);
  }
}

Once form is submitted we have to read base64 items and convert them to file. There are at least 2 solutions: pure LS or Java/LS2J

a) LotusScript using NotesMIMEHeader
Private Function saveBase64AsFile(base64 As String, filePath As string) As Boolean
	On Error GoTo ErrorHandler

	Dim stub As NotesDocument
	Dim stream As NotesStream
	Dim item As NotesMIMEEntity
	Dim header As NotesMIMEHeader
	Dim emb As NotesEmbeddedObject
	Dim fileName As String
	Dim contentType As string
	Dim base64File As String

	fileName = StrRightBack(filePath, "\")
	contentType = StrRight(Strleft(base64, ";"), ":")
	base64File = StrRight(Base64, ",")
	
	Call scriptLog.loginfo(fileName)
	Call scriptLog.loginfo(contentType)
	
	Set stub = db.Createdocument()
	Set item = stub.CreateMIMEEntity("Body")
	Set header = item.createHeader("Content-Disposition")
	Call header.setHeaderVal({attachment; filename="} & fileName & {"})

	Set stream = app.NotesSession.CreateStream()
	Call stream.WriteText(base64File)
	Call item.SetContentFromText(stream, contentType, ENC_BASE64)

	Call stream.Truncate
	Call stream.Close
	Call stub.Closemimeentities(True)

	Set emb = stub.Getattachment(fileName)
	Call emb.Extractfile(filePath)
	
	Exit Function
ErrorHandler:
	Error Err, Error
End Function
b) Java with LS2J using native classses.
import java.util.Base64;
import java.io.IOException;
import java.nio.file.*;

public class Base64ToFile{

	public boolean convert(String base64String, String filePath) {
		try {
			byte[] decodedImg = Base64.getDecoder().decode(base64String.getBytes());
			Path destinationFile = Paths.get(filePath);
			Files.write(destinationFile, decodedImg);
			return true;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}
}
UseLSX "*javacon"
Use "Base64ToFile"

Class Base64ToFile
	Private jSession As JavaSession
	Private jClass As Javaclass
	Private jObject As JavaObject
	Private jError As JavaError
	
	Sub New()
		Set jSession = New JavaSession
		Set jClass = jSession.GetClass("Base64ToFile")
		Set jObject = jClass.Createobject()
	End Sub
	
	Public Function convert(base64 As String, filePath As String) As Boolean
		convert = jObject.convert(base64, filePath)
	End Function
End Class

Tuesday, September 24, 2019

Create Excel files with LotusScript without Excel installed

One of my customer asked me to find a solution to create Excel files using LotusScript on server without Excel on it (well who wants to do install Excel and other tools on Server). Took some time but I have made a proof of concept using Apache POI and it worked very very nice. I have also made a LS2J cover so it's more easily for people who are not familiar with Java to create Excel files.

I put demo on my github account with some explanation so feel free to have a look on it: excel-apache-ls but if you wonder how it works, see snippet below:

Option Public
Option Declare

UseLSX "*javacon"
Use "Apache.Excel"

Sub Initialize
 Dim jSession As JavaSession
 Dim jClass As Javaclass
 Dim jObject As JavaObject
 Dim filepath As String
 Dim row As Integer

 Set jSession = New Javasession
 Set jClass = jSession.GetClass("explicants.office.Excel")
 Set jObject = jClass.Createobject()
 
 Call jObject.createSheet("sheet A-100")
 Call jObject.createSheet("sheet B-100")
 Call jObject.createSheet("sheet C-100")
 
 Call jObject.getSheet("sheet A-100")

 row = row + 1
 Call jObject.setCellValueString("lorem", row, 0)
 Call jObject.setCellValueString("ipsum", row, 1)
 Call jObject.setCellValueDouble(55, row, 2)
 
 row = row + 1
 Call jObject.setCellValueString("hello", row, 0)
 Call jObject.setCellValueString("world", row, 1)
 Call jObject.setCellValueDouble(200.50, row, 2)
 
 row = row + 1
 Call jObject.setCellValueString("gurli gris", row, 0)
 Call jObject.setCellValueString("george", row, 1)
 Call jObject.setCellValueDouble(0.505, row, 2)
 
 filepath = Environ("Temp") & Join(Evaluate({@Unique})) & ".xls"
 Call jObject.saveAsFile(filepath)
 
 MsgBox filepath
End Sub

Monday, January 04, 2016

Format datetime object in Lotus Script

Sometimes datetime output become tricky in Lotus Notes.

F.x. imagine you have code like this and you have german or any another locale on user's PC.
 Set dt = New NotesDateTime("")  
 Call dt.SetNow  
 msgbox Format$(dt.LSLocalTime, "dddd, dd. MMMM yyyy")  

Out would be
Tuesday, 22. December 2015

But what if you want output in german i.e.?
22. Dezember 2015

In such case you may want to use LS2J approach to display it properly to user

Below you will find a solution that either allow to set locale or use default locale.
 Option Public  
 Option Declare  
 UseLSX "*javacon"  
 Sub Initialize   
  On Error GoTo errhandler  
  Dim jSession As New JavaSession  
  Dim jCalendarClass As Javaclass, jLocaleClass As JavaClass, jSimpleDateFormatClass As JavaClass
  Dim jCalendar As Javaobject, jLocale As Javaobject, jSDF As JavaObject, jDate As Javaobject  
  Dim jError As JavaError  
  Dim dt As New NotesDateTime("")  
  Call dt.SetNow  
  'in order to initiate date - we have to use Calendar object  
  Set jCalendarClass = jSession.GetClass("java.util.Calendar")  
  Set jCalendar = jCalendarClass.getInstance()  
  Call jCalendar.set(Year(dt.DateOnly), month(dt.DateOnly) - 1, day(dt.DateOnly))  
  'initialize date object  
  Set jDate = jCalendar.getTime()  
  'IMPORTANT  
  'create locale (here we specify langauge/country code)   
  Set jLocaleClass = jSession.GetClass("java.util.Locale")  
  Set jLocale = jLocaleClass.CreateObject("(Ljava/lang/String;Ljava/lang/String;)V", "de", "DE")  
  'also you can use local settings, if you need that - enable line below  
  'Set jLocale = jLocaleClass.getDefault()  
  'output format  
  Set jSimpleDateFormatClass = jSession.GetClass("java.text.SimpleDateFormat")  
  Set jSDF = jSimpleDateFormatClass.CreateObject("(Ljava/lang/String;Ljava/util/Locale;)V", "dd. MMMM yyyy", jLocale)  
  'result  
  MsgBox jSDF.format(jDate)  
  done:  
  Exit Sub  
  errhandler:  
  Set jError = jSession.GetLastJavaError()  
  MsgBox "JavaError was " & jError.errorMsg  
  jSession.ClearJavaError  
  Resume done  
 End Sub  

Related topics:
Locale settings for date and time in IBM Domino and Notes

Thursday, October 03, 2013

IBM Designer Java Console effect?

I've faced up with interesting problems. I'm doing integration between MailChimp and Domino application. MailChimp service has very good API so it was not huge problem to push/poll data to/from it and we already implemented solution based on Java. The fun started when I tried to do LS2J part. My first request to java method came up with this dialog
That error does not happen if I enable Java Console in IBM Domino Designer. When Console is up - everything works perfect, otherwise this error:
LS2J Error: Threw java.lang.SecurityException: not allowed to access members in class interface java.util.Map
I can't explain how Java Console affect my security level, however definitely it does. I think it possibly grant users with more access when it is running and maybe there is an explanation why. Does anybody of you can explain that?