sâmbătă, 13 februarie 2016

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


[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
OmniFaces 2.4OmniFaces 2.3

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));
   }
  }
 });
}

Niciun comentariu:

Trimiteți un comentariu