Como carregar as imagens usando servlet?

4 respostas
wladyband

audação para todos,

sou novo como programador Java, e tenho feito meu projetos em JSF pois é através deles que tenho ganhado dinheiro, iniciei um projeto comercial aonde terei que mostrar as imagens dos produtos, graças a Deus conseguir implementar a gravação de imagens, e a abordagem que fiz foi gravar a imagem na pasta local no meu pc e o caminho no banco de dados MySQL.

A minha maior dificuldade foi tentar encontrar uma maneira de exigir essas imagens em tela, e a única forma que encontrei de fazer isso foi através de Servlet.

O meu código á um tempo atras funcionava tranquilamente, eu não sei se é porque estou deixando algum detalhe para traz, mas ele não funciona mais, preciso de ajuda porque eu não sei mexer direito com Servlet, e esse código eu encontrei na internet e antigamente ele funcionava perfeitamente.

essa é minha pagina XHTML feito em um projeto JSF;

<ui:composition template="/WEB-INF/template/LayoutPadrao.xhtml"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui" xmlns:o="http://omnifaces.org/ui">

    <ui:define name="titulo">Pesquisa Produto</ui:define>


    <ui:define name="corpo">

        <h:form id="frmPesquisaProduto">

            <h1>Novo Produto</h1>

            <p:messages autoUpdate="true" closable="true" />

            <p:toolbar style="margin-top: 20px">
                <p:toolbarGroup>
                    <p:commandButton value="Pesquisa"
                        action="#{pesquisaProdutoBean.pesquisa}" update="@form" />
                </p:toolbarGroup>
                <p:toolbarGroup align="right">
                    <p:button value="Novo" outcome="/produto/cadastro/CadastroProduto" />
                </p:toolbarGroup>
            </p:toolbar>

            <p:panelGrid columns="2" id="painel"
                style="width: 100%; margin-top: 20px" columnClasses="rotulo, campo">
                <p:outputLabel value="Nome do Produto" for="nomep" />
                <p:inputText id="nomep" size="60" maxlength="90"
                    value="#{pesquisaProdutoBean.filtro.nome}" />
            </p:panelGrid>


            <p:dataTable id="produtosTable"
                value="#{pesquisaProdutoBean.produtosFiltrados}" var="produto"
                style="margin-top: 20px" emptyMessage="Nenhum produto encontrado."
                rows="20" paginator="true" paginatorAlwaysVisible="false"
                paginatorPosition="bottom">
                <p:column headerText="Nome do Produto"
                    style="text-align: center; width: 100px">
                    <h:outputText value="#{produto.nomeproduto}" />
                </p:column>



                <p:column headerText="Foto" style="text-align: center; width: 200px">
                    <h:graphicImage value="../ShowImg?nomeFoto=#{produto.imagemproduto}" />
                </p:column>



                <p:column headerText="Valor do produto"
                    style="text-align: right; width: 120px">
                    <h:outputText value="#{produto.valorproduto}">
                        <f:convertNumber type="currency" />
                    </h:outputText>
                </p:column>
                <p:column headerText="Descrição do Produto"
                    style="text-align: center; width: 100px">
                    <h:outputText value="#{produto.descproduto}" />
                </p:column>
                <p:column style="width: 100px; text-align: center">
                    <p:button outcome="/produto/cadastro/CadastroProduto"
                        icon="ui-icon-pencil" title="Editar">
                        <f:param name="produto" value="#{produto.idproduto}" />
                    </p:button>


                    <p:commandButton icon="ui-icon-closethick" title="Excluir"

                        process="@this" update=":frmPesquisaProduto:produtosTable"
                        action="#{pesquisaProdutoBean.excluir}">

                        <f:setPropertyActionListener
                            target="#{pesquisaProdutoBean.produtoSelecionado}"
                            value="#{produto}" />

                        <p:confirm header="Confirmation"
                            message="Tem certeza que deseja excluir o produto #{pesquisaProdutoBean.produtoSelecionado.nomeproduto} ?"
                            icon="ui-icon-alert" />

                    </p:commandButton>


                </p:column>
            </p:dataTable>


            <p:confirmDialog global="true" showEffect="fade" hideEffect="fade">
                <p:commandButton value="SIM" type="button"
                    styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
                <p:commandButton value="NÃO" type="button"
                    styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
            </p:confirmDialog>



        </h:form>
    </ui:define>
</ui:composition>

Essa é a parte do código que não está funcionando na pagina;

<p:column headerText="Foto" style="text-align: center; width: 200px">
            <h:graphicImage value="../ShowImg?nomeFoto=#{produto.imagemproduto}" />
        </p:column>

E essa é a classe que fica responsavel em mostra as imagens na tela;

package br.com.comercial.controller;

import java.io.IOException;

import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;

public class ShowImgServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public ShowImgServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("image/jpeg");
        ServletOutputStream outimg = response.getOutputStream();

        String nomeFoto = request.getParameter("nomeFoto");
        String caminho = "C:/workspace Web/Projetos Profissionais/Fotos para teste/";// Aqui você coloca o caminho do diretório onde
                            // as imagens estão sendo armazenadas no
                            // servidor
        String foto = caminho + nomeFoto;

        RenderedOp src = JAI.create("fileload", foto);
        ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", outimg, null);
        encoder.encode(src);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}

Essa classe precisa dessa configuração para funciona;

<session-config>
    <session-timeout>30</session-timeout>
</session-config>



<servlet>
    <servlet-name>ShowImg</servlet-name>
    <servlet-class>br.com.comercial.controller.ShowImgServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>ShowImg</servlet-name>
    <url-pattern>/ShowImg</url-pattern>
</servlet-mapping>

Não se engane, eu fiz muitas tentativas para chegar a posta essa dúvida no fórum, estou desesperado para resolver isso, o cliente está me cobrando e eu com um código que funcionava não está funcionando;

Estou utilizando maven para baixar os artefatos.

4 Respostas

Rodrigos_Bragas

Olá, eu também sou iniciante. Recentemente passei por esse mesmo problema, mas conseguir resolver de 2 formas. Segue esse link, que no final do tópico, ou a minha ultima resposta, eu ensino como resolver isso com apenas um servlet que escreve quantas imagens você precisar. E no final dessa ultima resposta, eu deixei um link para outro tópico, que ensina a criar um diretório virtual no servidor de aplicação, que já mapeia as URLs das imagens, para se acessada no Browser. As duas soluções lhe permite salva as imagens fora da aplicação para evitar o deploy do servidor, onde as imagens se perderia. Esse é o link. Buscar imagem em JSP e Servlet em paginas geradas pelo servidor

wladyband

não tem como eu evitar o deploy no servidor porque o JSF ele trabalhar do lado do servidor, e constantemente é necessário fazer o deploy, você quer eu eu coloque o meu projeto no Github para você dá uma olhada para ver como está?

Rodrigos_Bragas

Essa solução é para você salvar as imagens em qualquer local que elas possam ser armazenadas como arquivo. Isto é, fora de um servidor de aplicação. Quem vai busca-las, é o Servlet. Não precisa de JSF. Pois o servlets vai criar uma URL unica para sua imagem. Por exemplo, você salva em pastas da seguinte forma: /ano/mes/dia/imagem1.jpg. Indiferente de onde as imagens estão vindo, o servlet ira criar uma URL unica apenas para a sua imagem. localhost:8080/meusite/imagens/ano/mes/dia/imagem1.jpg. Claro, quando salvar a imagem, ela não pode repetir o nome. Por isso você pode criar um loop que só execute se o nome existir. e a cada passada ele mude o nome da sua imagem para 1-imagem1.jpg, 2-imagem1.jpg, 3-imagem1.jpg, etc… As imagens só correm o risco de repetir o nome se forem salvas no mesmo dia. Mas o loop resolve isso.
Essa solução funcionou muito bem para mim. Pois eu posso usar a própria tag img do html(que tem no jsf), e informar o endereço online da imagem que foi gerado pelo servlet ‹img src=“http//localhost:8080/meusite/imagens/ano/mes/dia/imagem1.jpg” alt=“Imagem1” /›.
Olha a solução que eu coloquei para servlet. Eu busco as imagems na pasta /home/PC/uploads/imagens/… {Esse endereço é no linux, se fosse em windows, você colocaria em c:/qualquer_endereco ou d:/qualquer_endereco(confere o lado das barras em windows)}, e completo com o restante do diretório e nome salvos no banco de dados.
O que eu quero dizer, é que em momento algum você ira salvar as imagens dentro da pasta do servidor, seja ele Tomcat, jboss, glassfish. Só que eu ainda sou iniciante, todos os meus testes foram apenas localmente, ainda não hospedei nada online. Mas pelo que eu pesquisei, é mais ou menos assim. Só um detalhe, fazendo dessa maneira, você pode acessar suas imagens em qualquer domínio da web, você pode até mesmo criar um outro domínio e deixa-lo apenas para servir suas imagens com esse servlet. Seria como as imagem que você abre no navegado pelo google imagens através de uma URL com final .jpg ou .gif ou .png.

Vou te dar só um conselho. Imagino que o motivo que você esteja usando JSF, seja porque ainda não estudou jsp. Eu cai nessa armadilha também, tava acompanhando as apostilas da K19 e eles não passaram por JSP. Se você é iniciante, é obrigatório saber trabalhar com Servlets/JSP, nem que seja só o básico. Pois eu tinha pensado em desenvolver meu projeto em JSF, mas fui estudar servlets e jsp, apenas para não ficar com a consciência pesada.
Hoje eu não usaria JSF em nenhum dos meus projetos. Muitos podem até defende-lo, mas te garanto que até essas pessoas vão indicar você a aprender sevlets e jsp primeiro.

O único motivo que ainda não coloquei nada online ainda, é porque estou aprendendo NoSQL e BigData. Preciso desenvolver minhas aplicações em cima de bancos não relacionais.

Rodrigos_Bragas

Aqui esta o servlet caso não entendeu o outro:

package servlet;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/imagens/*")//Essa anotação substitui o web.xml e mapeia a partir da /pasta_das_imagens descrito logo abaixo, colocando localhost/meu_site/**imagens**/restante do endereço para mapear até o nome da imagem(Qualquer imagem)
public class Imagens extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String nomeImagem = request.getPathInfo().substring(1);
        File imagem = new File("diretórioWindows/uploads/pasta_das_imagens", nomeImagem);//Recebe ano/mes/dia/nome_imagem1.jpg
        Files.copy(imagem.toPath(), response.getOutputStream());
	}
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
}
Criado 15 de dezembro de 2015
Ultima resposta 16 de dez. de 2015
Respostas 4
Participantes 2