7

I get how you can use Expression Language to bind XPages controls to a Java Bean. Then it accesses the setters and getters automatically.

But how do you handle a file attachment?

What does that look like? I'd like to be able to I guess bind the file upload control to the bean. Save the attachment to "whatever" doc... whether it's the current or external document.. the bean should be able to handle that logic.

I guess I don't know how to get that file attachment into the in memory bean to be able to do anything with it like saving to a document.

any advice would be appreciated.

Update: This is a similar question to this: How to store uploaded file to local file system using xPages upload control?

But in that question the user wants to save to local disc. I'm looking to save to a document.

Thanks!

Community
  • 1
  • 1
David Leedy
  • 3,573
  • 16
  • 35

2 Answers2

11

You need to create a getter and setter in the bean using the com.ibm.xsp.component.UIFileuploadEx.UploadedFile class:

private UploadedFile uploadedFile;

public UploadedFile getFileUpload() {
    return uploadedFile;
}
public void setFileUpload( UploadedFile to ) {
    this.uploadedFile = to;
}

In the function that processes the bean data (e.g. a save function) you can check if a file was uploaded by checking if the object is null. If it's not null, a file was uploaded.

To process that uploaded file, first get an instance of a com.ibm.xsp.http.IUploadedFile object using the getServerFile() method. That object has a getServerFile() method that returns a File object for the uploaded file. The problem with that object is that it has a cryptic name (probably to deal with multiple people uploading files with the same name at the same time). The original file name can be retrieved using the getClientFileName() method of the IUploadedFile class.

What I then tend to do is to rename the cryptic file to its original file name, process it (embed it in a rich text field or do something else with it) and then rename it back to its original (cryptic) name. This last step is important because only then the file is cleaned up (deleted) after the code is finished.

Here's the sample code for the steps above:

import java.io.File;
import com.ibm.xsp.component.UIFileuploadEx.UploadedFile;
import com.ibm.xsp.http.IUploadedFile;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.RichTextItem;
import com.ibm.xsp.extlib.util.ExtLibUtil;  //only used here to get the current db

public void saveMyBean() {

  if (uploadedFile != null ) {

        //get the uploaded file
        IUploadedFile iUploadedFile = uploadedFile.getUploadedFile();

        //get the server file (with a cryptic filename)
        File serverFile = iUploadedFile.getServerFile();        

        //get the original filename
        String fileName = iUploadedFile.getClientFileName();    

        File correctedFile = new File( serverFile.getParentFile().getAbsolutePath() + File.separator + fileName );

        //rename the file to its original name
        boolean success = serverFile.renameTo(correctedFile);

        if (success) {
            //do whatever you want here with correctedFile

            //example of how to embed it in a document:
            Database dbCurrent = ExtLibUtil.getCurrentDatabase();
            Document doc = dbCurrent.createDocument();
            RichTextItem rtFiles = doc.createRichTextItem("files");
            rtFiles.embedObject(lotus.domino.EmbeddedObject.EMBED_ATTACHMENT, "", correctedFile.getAbsolutePath(), null);
            doc.save();

            rtFiles.recycle();
            doc.recycle();

            //if we're done: rename it back to the original filename, so it gets cleaned up by the server
            correctedFile.renameTo( iUploadedFile.getServerFile() );
        }


    }
 }
Mark Leusink
  • 3,567
  • 12
  • 21
  • This is a very cool way of doing it. I use the same with a repeat control where I can process each of the uploads directly in my Java bean ;-) – John Dalsgaard Oct 18 '13 at 14:00
  • it is not really clear for me how you bind the fileupload control to the managed bean? – Patrick Kwinten Dec 04 '15 at 12:35
  • Like this http://per.lausten.dk/blog/2012/02/creating-your-first-managed-bean-for-xpages.html. Add a getter and setter using the class I mentioned and bind that to a file upload control using expression language: "#{beanName.propertyName} – Mark Leusink Dec 05 '15 at 07:48
  • I have one issue, and I am not certain if this is a domino 9.0.1 issue or windows, or whatever I could make a new question if you want... When I do this, the File.seperator character is a semicolon ";". This changes the file name when the document is saved in the document. I am also unable to manually put a slash or backslash. Is anyone aware of a fix for that? – Greg May 27 '16 at 14:16
4

I have code that processes an uploaded file in Java. The file is uploaded with the normal fileUpload control and then I call the following Java code from a button (that does a full refresh - so that the document including the uploaded file is saved). In the Java code you can do whatever checks you want (filename, filesize etc.):

public void importFile() {

    facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();

    // get a handle an the uploaded file
    HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
    String fileUploadID = JSFUtil.findComponent("uploadFile").getClientId(FacesContext.getCurrentInstance());
    UploadedFile uploadedFile = ((UploadedFile) request.getParameterMap().get(fileUploadID));

    if (uploadedFile == null) {
        facesContext.addMessage("messages1", new FacesMessage(FacesMessage.SEVERITY_ERROR, "No file uploaded. Use the file upload button to upload a file.", ""));
        return;
    }

    File file = uploadedFile.getServerFile();

    String fileName = uploadedFile.getClientFileName();

    // Check that filename ends with .txt
    if (!fileName.endsWith(".txt")) {
        facesContext.addMessage("messages1", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error in uploaded file. The file must end with .txt", ""));
        return;
    }

    try {
        // Open the file
        BufferedReader br;

        br = new BufferedReader(new FileReader(file));
        String strLine;

        // Read File Line By Line
        while ((strLine = br.readLine()) != null) {
            // do stuff with the contents of the file
        }

        // Close the input stream
        br.close();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        facesContext.addMessage("messages1", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error in uploaded file. Please check format of file and try again", ""));
        return;
    }

    facesContext.addMessage("messages1", new FacesMessage(FacesMessage.SEVERITY_INFO, "File successfully uploaded", ""));
}

With a handle on the file object you can store the file in other documents using embedObject.

Per Henrik Lausten
  • 20,229
  • 3
  • 24
  • 72