Rabu, 22 Januari 2014

PDF handling


Read and open the PDF in a new browser window


The goal is to use JSF to open a PDF file inline in a new browser window without showing the full PDF path and filename for some (security) reasons. You can use either a h:commandLink or a h:commandButton for this:




value="Download PDF" action="#{myBean.downloadPDF}" target="_blank" />


 target="_blank">
value="Download PDF" action="#{myBean.downloadPDF}" />




Note: when using an ajax-capable command button/link from a library such as PrimeFaces, then don't forget to turn off the ajax capability by e.g. adding ajax="false" in case of PrimeFaces command components. It's namely not possible to download files using ajax, for the simple reason that JavaScript is due to security restrictions not capable of forcing a Save As dialogue from the client side on.



The downloadPDF() method of the backing bean MyBean.java sends the PDF to the HttpServletResponse as follows:



package mypackage;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletResponse;

public class MyBean {

// Constants ----------------------------------------------------------------------------------

private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.

// Actions ------------------------------------------------------------------------------------

public void downloadPDF() throws IOException {

// Prepare.
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

File file = new File(getFilePath(), getFileName());
BufferedInputStream input = null;
BufferedOutputStream output = null;

try {
// Open file.
input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);

// Init servlet response.
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + getFileName() + "\"");
output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);

// Write file contents to response.
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}

// Finalize task.
output.flush();
} finally {
// Gently close streams.
close(output);
close(input);
}

// Inform JSF that it doesn't need to handle response.
// This is very important, otherwise you will get the following exception in the logs:
// java.lang.IllegalStateException: Cannot forward after response has been committed.
facesContext.responseComplete();
}

// Helpers (can be refactored to public utility class) ----------------------------------------

private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
// Do your thing with the exception. Print it, log it or mail it. It may be useful to
// know that this will generally only be thrown when the client aborted the download.
e.printStackTrace();
}
}
}

}


The names of the getFilePath() and getFileName() are self-explaining, so there is no need to describe those methods.


If you don't care about showing request parameters or filenames in the URL, then you can also consider to use a FileServlet.



Copyright - There is no copyright on the code. You can copy, change and distribute it freely. Just mentioning this site should be fair.


(C) May 2006, BalusC




Source:http://balusc.blogspot.com/2006/05/pdf-handling.html

Tidak ada komentar:

Posting Komentar