Pessoal,
Estou com um grande desafio aqui: como pegar, atraves de um form html, uma imagem em JPG e transforma-la em BLOB para salva-la no BD?
Estou usando MySQL + Hibernate + Struts.
Pesquisei na net, mas não achei nada de util com essa minha configuração, geralmente é usando JDBC puro e nenhum exemplo, até agora encontrado, com Struts. Estou cheio de dúvida, de como receber essa imagem no action do struts, tranforma-la e ainda persistr com o Hibernate, se algume puder me da uma luz, agradeço.
Talvez isso ajude…
Receba a imagem e converta em bytes…
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication9;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
/**
*
* @author suporte
*/
@Entity
@Table(name = "imagem")
@NamedQueries({
@NamedQuery(name = "Imagem.findAll", query = "SELECT i FROM Imagem i"),
@NamedQuery(name = "Imagem.findById", query = "SELECT i FROM Imagem i WHERE i.id = :id")})
public class Imagem implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Basic(optional = false)
@Lob
@Column(name = "imagem")
private byte[] imagem;
public Imagem() {
}
public Imagem(Integer id) {
this.id = id;
}
public Imagem(Integer id, byte[] imagem) {
this.id = id;
this.imagem = imagem;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public byte[] getImagem() {
return imagem;
}
public void setImagem(byte[] imagem) {
this.imagem = imagem;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Imagem)) {
return false;
}
Imagem other = (Imagem) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "javaapplication9.Imagem[id=" + id + "]";
}
}
Beleza, criar a classe pra persistir e a tabela no BD é mole, na verdade eu não estou usando uma classe Imagem, estou colocando direto o campo BLOB na tabela que eu quero, que é a tabela funcionario, eu tenho um campo chamado foto do tipo blob dentro da tabela. Mas se for preciso faço uma classe soh pra imagem, mas como recuperar a imagem e converte-la, usando Struts?
Não é Mais fácil salvar em um pasta depois recuperar pelo caminho /fotos/imagen.jpg
mas se for obrigatório.
cria a coluna do tipo byte[] na entidade funcionario, nao precisa converter pra imagem, se quiser gravar num arquio eh so usar o metodo write do outputstream ou se quiser visualizar no browser faca do mesmo modo usando o outputstream do HttpServletResponse, mas setando o response.setContentType(“image/jpeg”).
Criei o atributo foto na classe Funcionario, coloquei como byte[], mas como que vou pegar o caminho que o usuario fornece no form html, jogar para uma action do struts e salvar no BD? Colocano o campo foto como byte[] basta eu salvar agora? Nao preciso converter nada, quero converter o arquivo em jpg para poder salva-lo no BD, ja que n aminha tabela o campo é do tipo blob, entendeu? Prefiro fazer direto no BD, pois fazendo com diretorios, vai ser mais dificil o bakcup
Na minha classe Funcionario, fiz o seguinte:
...
@Column(name = "foto")
private byte[] foto;
...
public byte[] getFoto() {
return foto;
}
public void setFoto(byte[] foto) {
this.foto = foto;
}
public void setFotoBlob(Blob imageBlob) {
this.foto = this.toByteArray(imageBlob);
}
/** Don't invoke this. Used by Hibernate only. */
public Blob getFotoBlob() {
return (Blob) Hibernate.createBlob(this.foto);
}
private byte[] toByteArray(Blob fromBlob) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
return toByteArrayImpl(fromBlob, baos);
}
catch (SQLException e) {
throw new RuntimeException(e);
}
catch (IOException e) {
throw new RuntimeException(e);
}
finally {
if (baos != null) {
try {
baos.close();
}
catch (IOException ex) {
}
}
}
}
private byte[] toByteArrayImpl(Blob fromBlob, ByteArrayOutputStream baos)
throws SQLException, IOException {
byte[] buf = new byte[4000];
InputStream is = fromBlob.getBinaryStream();
try {
for (;;) {
int dataSize = is.read(buf);
if (dataSize == -1)
break;
baos.write(buf, 0, dataSize);
}
}
finally {
if (is != null) {
try {
is.close();
}
catch (IOException ex) {
}
}
}
return baos.toByteArray();
}
...
Mas nao sei como usar isso, peguei em um tutorial do Hibernate
Alguma ideia de como posso fazer isso?
Dei mais uma pesquisada aqui e li que é colocar a anotação @Lob que o hibernate se vira, achei muito estranho, acho que pelo menos tenho que cosneguir pegar o arquivo em si atraves do form hmtl para ai sim o hibernate persistir, alguma ideia, por favor?
Fiz o seguinte:
Meu jsp:
...
<label>Foto:</label>
<input type="file" name="foto" />
...
CdastroFuncionarioForm: (BeanForm)
...
private String caminhoFoto;
public String getCaminhoFoto() {
return caminhoFoto;
}
public void setCaminhoFoto(String foto) {
this.caminhoFoto = foto;
}
...
CadastroFuncionarioAction: (Ação do Struts)
CadastrarFuncionarioForm funcionarioForm = (CadastrarFuncionarioForm) form;
Funcionario funcionario = new Funcionario();
File file = new File(funcionarioForm.getCaminhoFoto());
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte [(int) file.length()];
fis.read (bytes);
funcionario.setFoto(bytes);
Na minha entidade Funcionario coloquei os seguintes metodos:
...
@Column(name = "foto")
@Lob
private byte[] foto;
...
public byte[] getFoto() {
return foto;
}
public void setFoto(byte[] foto) {
this.foto = foto;
}
...
Aparece esse erro aqui, fazendo desse jeito:
javax.servlet.ServletException: java.lang.NullPointerException
java.lang.NullPointerException
java.io.File.(File.java:222)
catalogo.controle.actions.CadastrarFuncionarioAction.execute(CadastrarFuncionarioAction.java:40)
org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:425)
org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:228)
org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390)
Se alguem puder me ajudar a resolver esse problema e conseguir salvar a imagem direto no BD, eu acho que esta faltando eu pegar o caminho completo da imagem, mas enfim estou cheio de duvida pra fazer isso.
Pessoal,
Fiz assim na minha ação do Struts:
[code]
File file = new File(funcionarioForm.getFoto());
//File file = new File(“C:\Documents and Settings\Jefferson\Meus documentos\catalogo\publico\fotos\edson.jpg”);
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte [(int) file.length()];
fis.read (bytes);
// funcionario.setFoto(bytes);
BeanUtils.copyProperties(funcionario, funcionarioForm); [/code]
O problema é que só funciona se eu setar o camindo completo de algum arquivo na mão, como comentado na segunda linha do codigo, pelo que puder perceber o problema é que o meu CadastroFuncionarioForm esta com metodos diferentes da minha entidade Funcionario, entao quando eu mando copiar as propriedades de um para o outro me dar erro, como mudar isso?
Pessoal,
Continuo tentando salvar a iamgem no Bd com o codigo postado acima:
File file = new File(funcionarioForm.getCaminhoFoto());
FileInputStream fis = new FileInputStream(file);
byte[] bytes = new byte [(int) file.length()];
fis.read (bytes);
Não sei se essa é a melhotr maneira de fazer isso, se alguem souber de alguma outra maneira de fazer isso me ajude, por favor.
Com esse código, eu seto o meu atributo foto na minha classe Funcionario, no BeanForm tambem tenho esse mesmo atributo foto, mas mesmo assim nao consigo salvar no BD, consegui uma vez só, mas construindo a classe File setando o valor na mão, o erro agora é esse:
[code]javax.servlet.ServletException: BeanUtils.populate
org.apache.struts.util.RequestUtils.populate(RequestUtils.java:469)
org.apache.struts.action.RequestProcessor.processPopulate(RequestProcessor.java:818)
org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:194)
org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390)
root cause
java.lang.IllegalArgumentException: Cannot invoke catalogo.controle.forms.CadastrarFuncionarioForm.setCaminhoFoto - argument type mismatch
org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:1778)
org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:1759)
org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1648)
org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:1677)
org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:1022)
org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:811)
org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:298)
org.apache.struts.util.RequestUtils.populate(RequestUtils.java:467)
org.apache.struts.action.RequestProcessor.processPopulate(RequestProcessor.java:818)
org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:194)
org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:390)
[/code]
Se alguem puder me ajudar, agradeço.
tou com a mesma situação. Mas não consigui ainda salvar no banco a imagem.
Estou usando o Seam. Captura a imagem no meu bean, passo para minha entidade, do tipo byte[] com anotação @Lob maaaas ao pesistir o hibernate salva com NULL o campo.
Se achar uma solução aviso.
Tambem uso a anotação Lob e meu atributo é do tipo byte[] tambem, voce viu o pedaço de codigo que coloquei aqui? Criando um File e convertendo para bytes? Isso é a metade do caminho, quando eu coloco o caminho da foto na mao salva, quando tento pegar do form html que da erro.
Avisa sim, por favor, se eu descobrir algo, aviso tambem.
Valeu.
File file = new File(funcio.getFoto());
fis = new FileInputStream(file);
pstm.setBinaryStream(10, fis, (int) file.length());