Confesso: tentei encontrar um título menor pra descrever esta situação, mas não encontrei... Resumindo, o problema é este: se uma página JSF tivesse que exibir um documento PDF que já estivesse dentro do WebContent, era moleza: bastava criar um link apontando pra ele e ponto final. Mas, e se o arquivo estiver, por exemplo, em um servidor da rede cujo o usuário final não tenha acesso?
Uma solução é: importar o conteúdo deste arquivo PDF em um array de bytes e, com isto, enviá-lo para o Response
do JSF.
Vamos simular esta solução: criaremos uma aplicação simples, onde o usuário indica em qual caminho está o arquivo PDF, importa e visualiza o PDF no navegador. Ficará assim:
Para isto, basta umManagedBean
e uma página JSF. Sem mais delongas, eis o código, devidamente comentado:
index.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <h:head /> <h:body> <h:form> <h:panelGrid columns="2"> <h:outputText value="Arquivo:" /> <h:inputText value="#{control.arquivo}" /> <h:commandButton value="Importar Arquivo" action="#{control.importarArquivo}" /> <h:commandLink value="Visualizar PDF" action="#{control.visualizarPdf}" target="_blank" /> </h:panelGrid> </h:form> </h:body> </html>
Control.java:
@ManagedBean @SessionScoped public class Control implements Serializable { // Array de bytes que armazenará o conteúdo do arquivo PDF private byte[] conteudoPdf; // Caminho completo do arquivo informado pelo usuário. // Ex: C:\Meus Documentos\boletim.pdf private String arquivo; public String getArquivo() { return arquivo; } public void setArquivo(String arquivo) { this.arquivo = arquivo; } public void importarArquivo() { try { // Cria um objeto File a partir do caminho especificado File file = new File(arquivo); // Inicializa o array bytes com o tamanho do arquivo especificado. // Note a conversao para int, restringindo a capacidade maxima do // arquivo em 2 GB conteudoPdf = new byte[(int) file.length()]; // Cria um InputStream a partir do objeto File InputStream is = new FileInputStream(file); // Aqui o InputStream faz a leitura do arquivo, transformando em um // array de bytes is.read(conteudoPdf); // Fecha o InputStream, liberando seus recursos is.close(); } catch (Exception e) { e.printStackTrace(); } } public void visualizarPdf() { FacesContext fc = FacesContext.getCurrentInstance(); // Obtem o HttpServletResponse, objeto responsável pela resposta do // servidor ao browser HttpServletResponse response = (HttpServletResponse) fc .getExternalContext().getResponse(); // Limpa o buffer do response response.reset(); // Seta o tipo de conteudo no cabecalho da resposta. No caso, indica que o // conteudo sera um documento pdf. response.setContentType("application/pdf"); // Seta o tamanho do conteudo no cabecalho da resposta. No caso, o tamanho // em bytes do pdf response.setContentLength(conteudoPdf.length); // Seta o nome do arquivo e a disposição: "inline" abre no próprio // navegador. // Mude para "attachment" para indicar que deve ser feito um download response.setHeader("Content-disposition", "inline; filename=arquivo.pdf"); try { // Envia o conteudo do arquivo PDF para o response response.getOutputStream().write(conteudoPdf); // Descarrega o conteudo do stream, forçando a escrita de qualquer byte // ainda em buffer response.getOutputStream().flush(); // Fecha o stream, liberando seus recursos response.getOutputStream().close(); // Sinaliza ao JSF que a resposta HTTP para este pedido já foi gerada fc.responseComplete(); } catch (IOException e) { e.printStackTrace(); } } }
Boa Noite Maycon ,
ResponderExcluirobservei teu código e testei aqui e funcionou que é uma beleza. Gostaria muito de pedir sua ajuda em uma coisa.
O meu problema é o seguinte:
Tenho um botão em uma pagina que abre o Dialog e dentro deste eu quero abrir um pdf que esta em uma pasta no cliente e não consigo fazer ele ler e mostrar neste dialog ou mesmo salvar o documento na raiz do projeto para eu ler , mas não estou conseguindo nem abrir o pdf no dialog e nem mesmo gravar o pdf na raiz do projeto para abrir, por favor pode me ajudar???
Olá Paulo,
ResponderExcluirA partir de um servidor JSF, não é possível acessar diretamente um arquivo na máquina do cliente. Você precisará de um algum mecanismo para intermediar este processo, como por exemplo, um file upload... dê uma olhada neste post: https://community.oracle.com/thread/2152059?tstart=0
Agora, para exibir um PDF num dialog, dá pra fazer sim. Você está utilizando RichFaces, Primefaces?
Desde já obrigado pela resposta, vou te mostrar o codigo, quem sabe vc possa me ajudar:
ExcluirQuando eu gero o PDF é este bean que uso :
[code]
public class MontaManual {
private String programa_id;
private String programa_objetivo;
public static final String RESULT = "/pdf/out.pdf";
public String getPrograma_id() {
return programa_id;
}
public void setPrograma_id(String programa_id) {
this.programa_id = programa_id;
}
public String getPrograma_objetivo() {
return programa_objetivo;
}
public void setPrograma_objetivo(String programa_objetivo) {
this.programa_objetivo = programa_objetivo;
}
public void gerar_manual() throws IOException, DocumentException {
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(RESULT));
document.open();
PdfReader reader1 = new PdfReader("C:/Temp/CapaDoManual.pdf");
int n1 = reader1.getNumberOfPages();
PdfReader reader2 = new PdfReader("C:/Temp/SumarioDoManual.pdf");
int n2 = reader2.getNumberOfPages();
PdfReader reader3 = new PdfReader("C:/Temp/CorpoDoManual.pdf");
int n3 = reader3.getNumberOfPages();
PdfImportedPage page;
PdfCopy.PageStamp stamp;
Font f = new Font(FontFamily.TIMES_ROMAN, 10, Font.NORMAL);
for (int i = 0; i < n1; ) {
page = copy.getImportedPage(reader1, ++i);
stamp = copy.createPageStamp(page);
// add page numbers
PdfPTable foot = new PdfPTable(new float[] { 0.8f, 0.2f });
PdfPCell cell3 = new PdfPCell(new Phrase("PegasusIV - TT - AF - "+programa_id+" - " + programa_objetivo,f));
cell3.setHorizontalAlignment(Element.ALIGN_LEFT);
cell3.setVerticalAlignment(Element.ALIGN_TOP);
cell3.setBorder(1);
foot.addCell(cell3);
PdfPCell cell4 = new PdfPCell(new Phrase(String.format("Pagina %d / %d", i, n1 + n2 + n3),f));
cell4.setHorizontalAlignment(Element.ALIGN_RIGHT);
cell4.setVerticalAlignment(Element.ALIGN_TOP);
cell4.setBorder(1);
foot.addCell(cell4);
foot.setTotalWidth(page.getWidth() - document.leftMargin() - document.rightMargin());
foot.writeSelectedRows(0, -1, document.leftMargin(), document.bottomMargin(), stamp.getUnderContent());
stamp.alterContents();
copy.addPage(page);
}
for (int i = 0; i < n2; ) {
...
}
for (int i = 0; i < n3; ) {
...
}
document.close();
reader1.close();
reader2.close();
reader3.close();
}
}
[/code]
Este comentário foi removido pelo autor.
ResponderExcluirEste comentário foi removido pelo autor.
ResponderExcluirEste comentário foi removido pelo autor.
ResponderExcluirquando executo a gravação ele diz que não consegue, a mensagem é:
ResponderExcluir"Caused by: javax.faces.el.EvaluationException: java.io.FileNotFoundException: \pdf\out.pdf (O sistema não pode encontrar o caminho especificado)"
na minha pagina o codigo é este:
p:commandButton value="Manual" title="gera o MANUAL TECNICO do programa especificado" action="#{controlePaginaEspecificacaoTipo4.emitirManual(programa)}" oncomplete="dialogManual.show()" ajax="true" icon="ui-icon-document">
/p:commandButton>
...
h:form id="formManual">
p:panel id="panelManual">
p:media width="100%" height="600" value="/pdf/out.pdf" type="application/pdf"/>
/p:panel>
/p:dialog>
/h:form>}
se eu salvo o arquivo usando RESULT = "c:\\temp" eu não consigo ler na pagina.
Entende meu problema?
eu estou usando PRIMEFACES 4.0 HIBERNATE
Já procurei em muitos lugares mas não achei nada que eu possa usar.
desde já obrigado.
Olá Paulo! Analisei o seu código, e vi que já passei por alguns dos problemas que você está passando agora. Na verdade, eu tenho algumas sugestões que podem alterar um pouco a forma de fazer isto. Passa o seu e-mail pra mim pra gente trocar umas idéias.
Excluirboa noite maycon! Primeiramente queria dizer que gostei muito desse post e achei muito util...porém estou com um pequeno problema....como vc faria para fazer o upload de um PDF nesse servidor usando o FileUpload do primefaces? Ja procurei em tudo e não achei um tutoorial decente que use um arquivo PDF como exemplo...so achei com imagens!
ResponderExcluirVocê poderia mostrar um exemplo de como salvar o PDF no servidor usando o FileUpload? Agradeço desde já e aguardo sua resposta!
meu deus te amo, caralho procurei isso a internet inteira mas só teu código me ajudou. <3
ResponderExcluirMeu código está exatamente igual ao seu, no entanto ele nunca exibe em tela, somente baixa o relatorio pdf, vc pode me ajudar?
ResponderExcluirSegue meu código
public void getRelatotio(List lista, Long id) {
stream = this.getClass().getResourceAsStream("/jasper/memorando.jasper");
Map params = new HashMap();
baos = new ByteArrayOutputStream();
params.put("idDocumento", id);
try {
JasperReport report = (JasperReport) JRLoader.loadObject(stream);
JasperPrint print = JasperFillManager.fillReport(report, params, getConexao());
JasperExportManager.exportReportToPdfStream(print, baos);
response.reset();
response.setContentType("aplication/pdf");
response.setContentLength(baos.size());
response.setHeader("Content-disposition", "inline; filename=relatorio.pdf"); //se quiser forçar o download do relatorio mudar de inline para attachment
response.getOutputStream().write(baos.toByteArray());
response.getOutputStream().flush();
response.getOutputStream().close();
context.responseComplete();
fecharConexao();
} catch (JRException ex) {
new RuntimeException("Exceção no metodo GetRelatorio do Relatorio");
} catch (IOException ex) {
new RuntimeException("Exceção no metodo GetRelatorio do Relatorio");
}
}
Pessoal, eu quero carregar o ficheiro que estejo no disco C:, por exemplo e mostrar no dialog via p:media.
ResponderExcluirSerah que nao existe uma forma tao simples de o fazer???