0
votes

I have a JSF page + Bean to upload a file and preview the result (it's for images). In the bean the upload method puts the data (base64) in a list and the JSF page loops through the list to display the images.

So far it works as expected for the first image. But when I upload a second image there are two things that might go wrong:

  • the first image gets uploaded again instead
  • Or, with a little change in the code the second image does not get uploaded at all until I reselect the file again and upload it.

JSF page

<h:form enctype="multipart/form-data" id="uploadForm" prependId="false">

    <!-- here I loop through the list to preview the images -->
    <c:forEach var="image" items="#{bean.imageList}">
        <h:graphicImage value="#{image}" />
    </c:forEach>

    <!-- that's the upload -->
    <h:inputFile id="file" value="#{bean.uploadedFile}" />
    <h:commandButton value="submit" action="#{bean.uploadFile}" />
</h:form>

bean

private Part uploadedFile;                // the Part with the uploaded file
private ArrayList<String> imageList;      // the list of images (base64 encoded)

public void uploadFile() throws IOException{
    if(null != uploadedFile){
        String imageType = "data:" + uploadedFile.getContentType() + ";base64,";    // will be something like: "data:image/png;base64,"
        InputStream inputStream = uploadedFile.getInputStream();  // getting the inputStream from the Part
        byte[] imageData;                  // array to but the image data
        try(BufferedInputStream bis = new BufferedInputStream(inputStream)){          // converting the inputStream to a buffered one
            imageData = new byte[bis.available()];        // initializing the byte array with the right size
            bis.read(imageData);           // reading / writing the image data

            // HERE: if I comment out the next line, the second upload will upload the first image again.
            // but if I set the Part to null, the second upload will result in nothing (page reloads, no data uploaded) and I have to upload it again
            uploadedFile = null;
        }
        imageList.add(imageType + javax.xml.bind.DatatypeConverter.printBase64Binary(imageData));    // this adds the base64 image string to the list of images
    }
}

My bean is @ViewScoped (I need it to be that way for other things).

So my guess was that the Part uploadedFile just didn't get the new image data for the second file, but as I said, when setting it to null it just skips the second upload process.

Does anyone see what I am doing wrong?

1

1 Answers

2
votes

You might try the following.

    byte[] imageData = new byte[uploadedFile.getSize()];
    try (BufferedInputStream bis = new BufferedInputStream(inputStream)) {
        bis.read(imageData);
        uploadedFile.delete();
    }
  • Using Part.getSize()
  • Not relying on available() which makes no guarantee that all is available
  • Using delete() to clear the bean

(Not tried it myself.)