15

In PrimeFaces 8.0 the DefaultStreamedContent cannot be initialized like new DefaultStreamedContent(inputStream, contentType, name) because it has been deprecated, instead you shound use DefaultStreamedContent.builder().

Although while doing .stream() it asks for a SerializableSupplier<InputStream> instead of an InputStream like in the version before 8.0.

DefaultStreamedContent.builder().contentType(contentType).name(name).stream(is).build();
                                                                            ^^

How can I convert a InputStream to a SerializableSupplier?

Paolo Forgia
  • 6,572
  • 8
  • 46
  • 58

4 Answers4

26

Everthing is in the migration guide here: https://github.com/primefaces/primefaces/wiki/Migration-Guide.

in general the following will work:

DefaultStreamedContent.builder().contentType(contentType).name(name).stream(() -> is).build();

But the idea behind the change is a different.
If you use a RequestScoped bean to build the StreamedContent, your bean and therefore the StreamedContent will be created twice:

  1. when rendering the view
  2. when streaming the resource (this is a new browser request!)

In this case, your is will probably created 2 times. Most of the times this results in 1 useless IO access or DB call.

To only create the is one time, you should lazy initialize it via the supplier lambda:

DefaultStreamedContent.builder().contentType(contentType).name(name).stream(() -> new FileInputStream(....)).build();
tandraschko
  • 2,291
  • 13
  • 13
  • Is FileInputStream initialized in stream() autoclosable? –  Aug 17 '20 at 14:36
  • It will be close automatically, yes: https://github.com/primefaces/primefaces/blob/master/src/main/java/org/primefaces/application/resource/StreamedContentHandler.java#L124 – tandraschko Aug 18 '20 at 13:22
  • 2
    @tandraschko can you clarify for the latest version (Primefaces 10)? I cannot seem to find the place where the input stream gets closed anymore... – jansohn May 18 '21 at 12:42
0

This worked for me

DataHandler dataHandler = someBean.getFileData();
byte contents[] = IOUtils.toByteArray(dataHandler.getInputStream());
StreamedContent streamedContent = DefaultStreamedContent.builder()
                    .name(someBean.getFileName())
                    .contentType("application/octet-stream")
                    .stream(() -> new ByteArrayInputStream(contents)).build();
David Buck
  • 3,752
  • 35
  • 31
  • 35
0

The lazy initialize answer above by @tandraschko did not work for me in Netbeans using java 8. I had to have the FileInputStream created before injecting it into the builder.

So my code looks like :

public StreamedContent getFiledownload() {
        FileInputStream fis = new FileInputStream("...");
        filedownload = DefaultStreamedContent.builder()
                .contentType("...")
                .name("...")
                .stream(() -> fis)
                .build();
        return filedownload;
    }

Thought I would comment just in case someone else was running into compiling issues.

-1

For MySQL stored image I use this:

resultset = statement.executeQuery("call sp_query()");
if(resultset.next()) {

    new DefaultStreamedContent();
    StreamedContent photo = DefaultStreamedContent.builder().contentType("contentType").name("name").stream(() -> resultset.getBinaryStream("picture")).build());
}

// Close the connection
con.close();
Paolo Forgia
  • 6,572
  • 8
  • 46
  • 58