views:

2655

answers:

2

I am currently looking in to some file uploading using Java Server Faces. I've found this great introduction to it using RichFaces. However, I have some troubles understanding the process here.

First the user selects a file and if the immediate upload is set to true the file is processed using ajax, so far so good. When it comes to the next step however, the listener on the Bean-side the following confuses me:

public void listener(UploadEvent event) throws Exception{
    UploadItem item = event.getUploadItem();

    File f = item.getFile();

    System.out.println(f.getAbsolutePath());
}

The Absolute path is to a temp directory on my computer, sure I understand that, but how would you make the file available to the webbapplication? My application is deployed as a WAR-file. Is it possible to Upload it to the WAR? Might sound stupid or so, but it might actually be handy.

I am fully aware that I can rename the file to copy it to a new location, but is that the way to go?

+2  A: 

Writing things to your WAR directory (assuming the WAR is even exploded as a directory) is, in generally, a bad idea (for the same reasons that storing your data in your application directory is usually a bad idea).

You'd probably want it to end up in a persistence store, usually a database. Exactly how you manage that is up to you - whether you use the file system and store a reference in the database or store a BLOB in the database directly and whether you use JDBC or JPA or Hibernate, etc.

The list of uploaded files could then be read from the database by refreshing the panel that contained them using something like <a4j:support event="onuploadcomplete" reRender="info" />.

A file download servlet (if RichFaces doesn't have one) is fairly easy to write.

McDowell
As I thought, thanks for clearing it up. Guess I will have to look into creating a download servlet.
Filip Ekberg
Did you ever figure out how to create that download servlet, Filip? I've played around with the fileUpload component and I can't for the life of me figure out where a file goes after I upload it.
Matt S
+1  A: 

Not sure how much help this is (and probably way too late!), but this is the code I use on the server side, equivalent to your listener.

public String uploadFile(UploadEvent event) {
    UploadItem item = event.getUploadItem();

    String name = "unnamed_attachment";
    byte[] data = item.getData();

    try {
        name = FilenameUtils.getName(item.getFileName());
        data = FileUtils.readFileToByteArray(item.getFile());
        logger.info("data.length = " + data.length);
        UploadDetails details = new UploadDetails(); // This is a javabean that gets persisted to database (actually a ejb3 entity bean, but thats irrelevant)

        details.setBytes(data);
        details.setResume(true);
        // Save to database here 

    } catch (Exception e) {
        FaceletsUtil.addSystemErrorMessage();
        logger.error(e, e);
    }
    return null;
}

The big question remaining is you say "how would you make the file available to the webbapplication?". The byte array is available immediately. If you want to re-download the file, you can provide it as a link to a method in a JSF session/view bean like:

<h:commandButton action="#{Manager.downloadFile}" value="Download report">                                </h:commandButton>

public void downloadFile() {
    final HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();

    response.setHeader("Content-Disposition", "attachment;filename=radar-report" + new Date() + ".pdf"); // or whatever type you're sending back
    try {
        response.getOutputStream().write(uploadDetails.getBytes()); // from the UploadDetails bean
        response.setContentLength(uploadDetails.getBytes().length);
        response.getOutputStream().flush();
        response.getOutputStream().close();
    } catch (IOException e) {
        logger.error(e, e);  
    }
    FacesContext.getCurrentInstance().responseComplete();
}
Greg