Como converter de array de bytes para a imagem original?

11 respostas
A

Visando tentar gravar numa tabela Blob gostaria de converter imagem em bytes e depois desconverter pra exibir pro usuário... Aliás essa
é a únicamente maneira em termos de Blob, né? Antes de dar NullPointerException ele gravava só que só os bytes tanto que pro usuário aparecia apenas um
monte de número (array de bytes)... Pra retornar no JSP page faço o esquema normal como se fosse String né?

/**
     * Método Action
     * @return SUCESS
     * @return INPUT
     * @throws IOException
     * @throws FileNotFoundException
     * */
    @SuppressWarnings("null")
	@Override
	public String execute() throws IOException, FileNotFoundException, FileUploadException, SizeLimitExceededException    
	{    
    	if (imagemDoUsuario == null)
    	{    
    		System.out.println("É preciso apontar o arquivo a ser importado!");  
    		return INPUT;  
	    }  
	    
    	if (!imagemDoUsuarioContentType.startsWith("image"))  
    	{  
	       System.out.println("O formato do arquivo é inválido! Não é uma imagem!");  
	       return INPUT;  
	    }  
	    
	    if(imagemDoUsuario.length() >= 2097152)  
	    {  
	       throw new SizeLimitExceededException("A imagem anexada ultrapassa o tamanho máximo permitido!");    
	    }  
	   
	    FileInputStream in = new FileInputStream(imagemDoUsuario);    
	    byte[] buffer = new byte[(int)imagemDoUsuario.length()];    
	    System.out.println("Tamanho da Imagem: " + imagemDoUsuario.length() + " Bytes");
	  
	    OutputStream outputStream = null;    
	    InputStream inputStream = null;    
	   
	    int readBytes = 0;    
	 
	  /*-> NullPointerException aqui...*/ while ((readBytes = inputStream.read(buffer, 0 , (int) imagemDoUsuario.length()))!= -1) //-> NullPointerException aqui...
	    {    
	      outputStream.write(buffer, 0, readBytes);    
	    }  
	   
	    in.read(buffer);  
	   
	    pessoaImagem.setImagem(buffer);    
	    pessoaImagemDAO.salvarPessoaImagem(pessoaImagem);    
	  
	    inputStream.close();    
	    outputStream.close();    
	   
	    return populaTodasImagens();    
	}

11 Respostas

ViniGodoy

Você pode acaso sabe em que formato essa imagem está?

A

Sei… Fiz a seguinte validação Vini:

if (imagemDoUsuarioContentType.startsWith("image"))

Isso me garante que vai ser do tipo imagem não aceita outros como .pdf .doc .xls etc…

ViniGodoy

Sim, mas isso só diz que a imagem é uma imagem, não o seu formato.

Se o content type estiver corretamente especificado, então, você deverá ter uma / e o formato da imagem (gif, jpeg, etc). Com isso em mãos, basta usar a classe ImageIO para carregar a sua imagem no formato correto na memória, e então utiliza-la.

Outra coisa, seu código pode ficar muito mais legível se você usar code-guards, ou seja, deixar as exceptions para a condição principal do if, e remover os elses. Isso evita identação e evita ter que ler o código todo para perceber que fora daquele if ele não faz nada. Veja:

public String execute() throws IOException, FileNotFoundException, FileUploadException, SizeLimitExceededException  
{  
   if (imagemDoUsuario == null)  {  
       System.out.println("É preciso apontar o arquivo a ser importado!");
       return INPUT;
   }
   if (!imagemDoUsuarioContentType.startsWith("image"))  {
      System.out.println("O formato do arquivo é inválido! Não é uma imagem!");
      return INPUT;
   }

   if(imagemDoUsuario.length() >= 2097152)  {
      throw new SizeLimitExceededException("A imagem anexada ultrapassa o tamanho máximo permitido!");  
   }

   FileInputStream in = new FileInputStream(imagemDoUsuario);  
   byte[] buffer = new byte[(int)imagemDoUsuario.length()];  

   OutputStream outputStream = null;  
   InputStream inputStream = null;  
   int readBytes;  

   while ((readBytes = inputStream.read(buffer, 0 , 10000))!=-1){  
      outputStream.write(buffer, 0, readBytes);  
   }
   in.read(buffer);

   pessoaImagem.setImagem(buffer);  
   pessoaImagemDAO.salvarPessoaImagem(pessoaImagem);  

   inputStream.close();  
   outputStream.close();  

   return populaTodasImagens();  
}

PS: Esse código foi você quem fez? Pq ele é bem diferente do que você costuma a postar por aqui.

A

Oi Vini,
hehehe... Sim fui eu que fiz este código... Acho que isso é um elogío :D 8) ... É que tive estudando muito estou subindo de degrau... hehehe...

Vini, o código que você sugeriu de fato é bem melhor, já o adaptei... A questão é que minha dúvida ainda se mantem pois ainda acontece o NullPointerException na linha
abaixo onde fiz o comentário, tal como se a forma pela qual estou convertendo a imagem x em bytes... Está correta?....

/**
     * Método Action
     * @return SUCESS
     * @return INPUT
     * @throws IOException
     * @throws FileNotFoundException
     * */
    @SuppressWarnings("null")
	@Override
	public String execute() throws IOException, FileNotFoundException, FileUploadException, SizeLimitExceededException    
	{    
    	if (imagemDoUsuario == null)
    	{    
    		System.out.println("É preciso apontar o arquivo a ser importado!");  
    		return INPUT;  
	    }  
	    
    	if (!imagemDoUsuarioContentType.startsWith("image"))  
    	{  
	       System.out.println("O formato do arquivo é inválido! Não é uma imagem!");  
	       return INPUT;  
	    }  
	    
	    if(imagemDoUsuario.length() >= 2097152)  
	    {  
	       throw new SizeLimitExceededException("A imagem anexada ultrapassa o tamanho máximo permitido!");    
	    }  
	   
	    FileInputStream in = new FileInputStream(imagemDoUsuario);    
	    byte[] buffer = new byte[(int)imagemDoUsuario.length()];    
	    System.out.println("Tamanho da Imagem: " + imagemDoUsuario.length() + " Bytes");
	  
	    OutputStream outputStream = null;    
	    InputStream inputStream = null;    
	   
	    int readBytes = 0;    
	 
	  /*-> NullPointerException aqui...*/ while ((readBytes = inputStream.read(buffer, 0 , (int) imagemDoUsuario.length()))!= -1) //-> NullPointerException aqui...
	    {    
	      outputStream.write(buffer, 0, readBytes);    
	    }  
	   
	    in.read(buffer);  
	   
	    pessoaImagem.setImagem(buffer);    
	    pessoaImagemDAO.salvarPessoaImagem(pessoaImagem);    
	  
	    inputStream.close();    
	    outputStream.close();    
	   
	    return populaTodasImagens();    
	}
A

Estou tentando usar a classe ImageIO que você me recomendou... Está um pouquinho complicado de entender hehehe...

abraço, :shock:

/**
     * Método Action
     * @return SUCESS
     * @return INPUT
     * @throws IOException
     * @throws FileNotFoundException
     * */
    @SuppressWarnings("null")
	@Override
	public String execute() throws IOException, FileNotFoundException, FileUploadException, SizeLimitExceededException    
	{    
    	if (imagemDoUsuario == null)
    	{    
    		System.out.println("É preciso apontar o arquivo a ser importado!");  
    		return INPUT;  
	    }  
	    
    	if (!imagemDoUsuarioContentType.startsWith("image"))  
    	{  
	       System.out.println("O formato do arquivo é inválido! Não é uma imagem!");  
	       return INPUT;  
	    }  
	    
	    if(imagemDoUsuario.length() >= 2097152)  
	    {  
	       throw new SizeLimitExceededException("A imagem anexada ultrapassa o tamanho máximo permitido!");    
	    }  
	   
	    BufferedImage image = ImageIO.read(imagemDoUsuario);  
	   	    
	/*    FileInputStream in = new FileInputStream(imagemDoUsuario);    
	    byte[] buffer = new byte[(int)imagemDoUsuario.length()];    
	    System.out.println("Tamanho da Imagem: " + imagemDoUsuario.length() + " Bytes");
	  
	    OutputStream outputStream = null;    
	    InputStream inputStream = null;    
	   
	    int readBytes = 0;    
	 
	  -> NullPointerException aqui... while ((readBytes = inputStream.read(buffer, 0 , (int) imagemDoUsuario.length()))!= -1) //-> NullPointerException aqui...
	    {    
	      outputStream.write(buffer, 0, readBytes);    
	    }  
	   
	    in.read(buffer);  */
	   
	    pessoaImagem.setImagem((Blob) image);    
	    pessoaImagemDAO.salvarPessoaImagem(pessoaImagem);    
	  
/*	    inputStream.close();    
	    outputStream.close();  */  
	   
	    return populaTodasImagens();    
	}
A

Olá, belezinha?

Veja como ficou, fiz a adpatação:

/**
     * Método Action
     * @return SUCESS
     * @return INPUT
     * @throws IOException
     * @throws FileNotFoundException
     * */
	@Override
	public String execute() throws IOException, SizeLimitExceededException {    
		if (imagemDoUsuario == null) {  
			System.out.println("A imagem chegou nula!");
			return INPUT; 
		}
		
	    if (!imagemDoUsuarioContentType.startsWith("image")) {  
		   throw new IllegalArgumentException("O formato do arquivo é inválido! Não é uma imagem!");  
	    }  
		
	    if (imagemDoUsuario.length() > 2097152) {  
		   throw new SizeLimitExceededException("A imagem anexada ultrapassa o tamanho máximo permitido!");    
		}  
		  
	    InputStream entrada = new FileInputStream(imagemDoUsuario);    
	    OutputStream saida = new ByteArrayOutputStream();    
		   
	    byte[] buffer = new byte[4096]; //buffer de 4KB  
	    int bytesLidos = -1;  
	
	    while ((bytesLidos = entrada.read(buffer, 0, buffer.length)) != -1) {  
	      saida.write(buffer, 0, bytesLidos);  
	   }  
	
		saida.flush();  
		saida.close();  
		entrada.close();  
		    
		buffer = ((ByteArrayOutputStream) saida).toByteArray();  
		
		pessoaImagem.setImagem(buffer);    
		pessoaImagemDAO.salvarPessoaImagem(pessoaImagem);    
		   
		return populaTodasImagens();    
    }

A questão é que no JSP ele mostra array de bytes hehehe... Por favor vide o anexo...

Segue meu JSP:

<%-- 
    Document   : panel_grid_pessoas
    Created on : 14/09/2010
    Author     : André Asantos
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="/struts-tags" prefix="s"%>
<%@ taglib tagdir="/WEB-INF/tags/ext" prefix="ext"%>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sistema de Administração de Conteúdo Digital</title>
</head>
<script type="text/javascript">

	/**
      * Provê um menu que pode ser utilizado em varias partes do sistema, como contexto ou menustrip
      */
      function crudMenuClick(e){
          var contextMenu = new Ext.menu.Menu({
			items:[
					{
	  					icon:'imagens/adminreports.png',
	  					text:'Modificar',
	  					cls:'x-btn-text-icon',
	  					handler:function(){crudPessoa(2);}
					},
					{
			  			icon:'imagens/cross.png',
			  			text:'Remover',
			  			cls:'x-btn-text-icon',
			  			handler:function(){crudPessoa(3);}
					}
			]
		});
         e.stopEvent();
         var xy = e.getXY();
         contextMenu.showAt(xy);
      }
</script>
<body>
<ext:body>
	<ext:viewport id="viewGaleriaDeFoto" layout="fit">
		<ext:grid.gridPanel id="viewGaleriaDeFoto" layout="fit" frame="true" loadMask="true" 
					onDblclick="crudPessoa(2);" onContextmenu="function(e){crudMenuClick(e);}" stripeRows="true">
		<ext:toolbar id="menuCrud" toolbarType="tbar" style="border:0;">
				<ext:toolbar.separator />
				<ext:toolbar.button text="Adicionar" 
									cls="x-btn-text-icon"
									icon="imagens/addicon2.gif"
									onClick="crudPessoa(1);"  />
				<ext:toolbar.button text="Modificar" 
									cls="x-btn-text-icon"
									icon="imagens/adminreports.png" 
									onClick="crudPessoa(2);"/>
				<ext:toolbar.button text="Remover" 
									cls="x-btn-text-icon"
									icon="imagens/cross.png" 
									onClick="crudPessoa(3);"/>
				<ext:toolbar.separator />
				<ext:toolbar.splitButton text="Exportar" >
					<ext:menu>
						<ext:menu.item id="excel" 
									   text="Excel" 
									   cls="x-btn-text-icon" 
									   icon="imagens/excel.png"/>
					 </ext:menu>
				</ext:toolbar.splitButton>
		</ext:toolbar>
			<ext:grid.columnModel sm="new Ext.grid.RowSelectionModel({singleSelect:true})">
			
			
				<ext:grid.column dataIndex="imagem" header="Imagem" sortable="true" width="300"></ext:grid.column>
				
			</ext:grid.columnModel>
			
			<ext:data.store url="resultuploaddasimagens.action" autoLoad="true" storeId="galeriaDeFotoStores">
				<ext:data.jsonReader root="linhas" totalProperty="total">
					<ext:data.fields>
					
						<ext:data.field name="imagem" />
			
					</ext:data.fields>
				</ext:data.jsonReader>
			</ext:data.store>
			<ext:pagingToolbar id="pagingBar" toolbarType="bbar" pageSize="30"
				displayInfo="true" displayMsg="Mostrando {0} - {1} de {2}"
				emptyMsg="Nenhuma informação encontrada" autoShow="true"
				autoWidth="true" style="border:0;" />
		</ext:grid.gridPanel>
	</ext:viewport>
</ext:body>
</body>
</html>

A

Alguma dica?

leandro.alves

Que tal :

Servlet…

response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setContentType("image/bmp");

BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());

try{

       ImageIO.write(	ImageIO.read(blob.getBinaryStream()), 
			"JPG", 
			bos); 
}finally{
        	
       bos.flush();
        	
       bos.close();        	
        	
}

Não sei se serve para o seu contexto, mas…

Normalmente seria algo do tipo…

<iimg src="getImageServlet.do" .... />
A

ViniGodoy:
Sim, mas isso só diz que a imagem é uma imagem, não o seu formato.

Se o content type estiver corretamente especificado, então, você deverá ter uma / e o formato da imagem (gif, jpeg, etc). Com isso em mãos, basta usar a classe ImageIO para carregar a sua imagem no formato correto na memória, e então utiliza-la.

Outra coisa, seu código pode ficar muito mais legível se você usar code-guards, ou seja, deixar as exceptions para a condição principal do if, e remover os elses. Isso evita identação e evita ter que ler o código todo para perceber que fora daquele if ele não faz nada. Veja:

public String execute() throws IOException, FileNotFoundException, FileUploadException, SizeLimitExceededException  
{  
   if (imagemDoUsuario == null)  {  
       System.out.println("É preciso apontar o arquivo a ser importado!");
       return INPUT;
   }
   if (!imagemDoUsuarioContentType.startsWith("image"))  {
      System.out.println("O formato do arquivo é inválido! Não é uma imagem!");
      return INPUT;
   }

   if(imagemDoUsuario.length() >= 2097152)  {
      throw new SizeLimitExceededException("A imagem anexada ultrapassa o tamanho máximo permitido!");  
   }

   FileInputStream in = new FileInputStream(imagemDoUsuario);  
   byte[] buffer = new byte[(int)imagemDoUsuario.length()];  

   OutputStream outputStream = null;  
   InputStream inputStream = null;  
   int readBytes;  

   while ((readBytes = inputStream.read(buffer, 0 , 10000))!=-1){  
      outputStream.write(buffer, 0, readBytes);  
   }
   in.read(buffer);

   pessoaImagem.setImagem(buffer);  
   pessoaImagemDAO.salvarPessoaImagem(pessoaImagem);  

   inputStream.close();  
   outputStream.close();  

   return populaTodasImagens();  
}

PS: Esse código foi você quem fez? Pq ele é bem diferente do que você costuma a postar por aqui.

Vini, como vai?

Se eu usar ImageIO não preciso converter de imagem pra array de bytes? Como convertí pra array de bytes será q tá aparecendo desta forma no jsp por que eu não desconvertí?

A

Por favor, o mapeamento da minha tabela no JPA precisa a coluna Blob receber alguma anotação do tipo @Lob?

package br.com.editorasaraiva.repositoriodigital.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 * Pessoa Imagem
 * <p>Mapeamento objeto relacional das Imagens que uma Pessoa possa possuir.</p>
 * 
 * @author André Asantos
 * @version 1.0
 * <p>Data de criação: 23/09/2010</p>
 * <p>Copyright © 2005 - 2010 Editora Saraiva</p>
 */

@Entity
@Table(name="TBL_PESSOA_IMAGEM")
public class PessoaImagem implements Serializable {

	/**
	 * Versão serial
	 * 
	 */
    private static final long serialVersionUID = 1L;

    //mapeamento
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id_pessoa_imagem")
    private Integer idPessoaImagem;

    @Column(name="imagem")
    @Lob
    private byte[] imagem;
    
    @ManyToOne
    @JoinColumn(name = "id_pessoa_info_fk", referencedColumnName = "id_pessoa_info")
    private PessoaInfo pessoaInfo;
    
    
    //getters e setters
	/**
	 * @param idPessoaImagem the idPessoaImagem to set
	 */
	public void setIdPessoaImagem(Integer idPessoaImagem) {
		this.idPessoaImagem = idPessoaImagem;
	}

	/**
	 * @return the idPessoaImagem
	 */
	public Integer getIdPessoaImagem() {
		return idPessoaImagem;
	}

	/**
	 * @param dados the imagem to set
	 */
	public void setImagem(byte[] dados) {
		this.imagem = dados;
	}

	/**
	 * @return the imagem
	 */
	public byte[] getImagem() {
		return imagem;
	}

	/**
	 * @return the pessoaInfo
	 */
	public PessoaInfo getPessoaInfo() {
		return pessoaInfo;
	}

	/**
	 * @param pessoaInfo the pessoaInfo to set
	 */
	public void setPessoaInfo(PessoaInfo pessoaInfo) {
		this.pessoaInfo = pessoaInfo;
	}
}
A

Vou tentar criar uma Action específica pra retornar a imagem no JSP…

Criado 6 de outubro de 2010
Ultima resposta 7 de out. de 2010
Respostas 11
Participantes 3