Quantcast
Channel: OmniFaces & JSF Fans
Viewing all articles
Browse latest Browse all 74

[OmniFaces utilities (2.3)] Send a file to the response whose content is provided via given output stream callback

$
0
0

[OmniFaces utilities] The sendFile() sends a file to the response whose content is provided via given output stream callback. The content type will be determined based on file name. The content length will not be set because that would require buffering the entire file in memory or temp disk. The client may receive a download of an unknown length and thus the download progress may be unknown to the client. If this is undesirable, write to a temp file instead and then use Faces#sendFile(File, boolean). The FacesContext#responseComplete() will implicitly be called after successful streaming.

Note The caller should preferably not catch the IOException thrown by this method,but just re-declare it in the action method.The Servlet container will handle it.

Method

Usage

The relative path of the file to download is /resources/default/images/rafa.png and the user should see at download the file as rafaelnadal.png:

import org.omnifaces.util.Callback;
import org.omnifaces.util.Callback.Output;
import org.omnifaces.util.Faces;
...
public void downloadFile() throws IOException {
 Faces.sendFile("rafaelnadal.png", true, new Callback.Output() {
  @Override
  public void writeTo(OutputStream output) throws IOException {

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

   Path path = Paths.get(externalContext.getRealPath("/resources/default/images/rafa.png"));

   long contentLength = (long) Files.getAttribute(path, "basic:size", NOFOLLOW_LINKS);
   if (contentLength != -1) {
       externalContext.setResponseHeader("Content-Length", String.valueOf(contentLength));
   }

   long size = 0;

   try (ReadableByteChannel inputChannel = Channels.newChannel(Files.newInputStream(path));
        WritableByteChannel outputChannel = Channels.newChannel(output)) {
        ByteBuffer buffer = ByteBuffer.allocateDirect(10240);
        while (inputChannel.read(buffer) != -1) {
               buffer.flip();
               size += outputChannel.write(buffer);
               buffer.clear();
        }
   }

   if (contentLength == -1 && !Faces.getExternalContext().isResponseCommitted()) {
       externalContext.setResponseHeader("Content-Length", String.valueOf(size));
   }
  }
 });
}

Or, you can obtain the same thing by using several OmniFaces utilities:

import org.omnifaces.util.Callback;
import org.omnifaces.util.Callback.Output;
import org.omnifaces.util.Faces;
import org.omnifaces.util.Utils;
...
public void downloadFile() throws IOException {
 Faces.sendFile("rafaelnadal.png", true, new Callback.Output() {
  @Override
  public void writeTo(OutputStream output) throws IOException {
   long size = Utils.stream(Faces.getResourceAsStream("/resources/default/images/rafa.png"), output);
   if (!Faces.getExternalContext().isResponseCommitted()) {
        Faces.getExternalContext().setResponseHeader("Content-Length", String.valueOf(size));
   }
  }
 });
}


Viewing all articles
Browse latest Browse all 74

Trending Articles