Tenho um bean no qual eu recupero a sua foto de um banco de dados:
publicclassPessoa{privateintid;privateStringnome;privateInputStreamfoto;// getters e setters omitidos}
publicclassPessoaDAO{// outros métodos omitidosprivatevoidpopulaBean(ResultSetrs,Pessoabean)throwsSQLException{bean.setId(rs.getInt("id"));bean.setNome(rs.getString("nome"));bean.setFoto(rs.getBinaryStream("foto"));}}
Quando eu tento exibir essa foto (em um Servlet, por exemplo) o JDBC lança uma exceção que o objeto já foi fechado (o ResultSet).
PessoaDAOdao=newPessoaDAO();intidPessoa=99;Pessoabean=dao.obter(idPessoa);InputStreamentrada=bean.getFoto();try{// carrega o arquivo na Servletresponse.setContentType("application/octet-stream");byte[]buffer=newbyte[1024];intbytesLidos=-1;while((bytesLidos=entrada.read(buffer,0,1024))>0)// a execção é lançada aqui{response.getOutputStream().write(buffer,0,bytesLidos);}response.getOutputStream().flush();response.getOutputStream().close();entrada.close();}catch(IOExceptionioE){ioE.printStackTrace();}
Exceção: [Microsoft][SQLServer 2000 Driver for JDBC]Object has been closed.
Dúvida: Há alguma maneira de desvincular o InputStream originado do ResultSet passado ao InputStream do bean (Pessoa.foto)?
Você tenta acessar este endereço, o ResultSet já está fechado.
O que você precisa é que o InputStream “foto” tenha uma “cópia” deste InputStream e não seja o mesmo.
Espero que seja isso… :roll:
ze_kiefa
Esse é o objetivo: como fazer?
Leandro_Carvalho
Continuo achando que seu problema é conceitual… heheheh
Você precisa transportar o “byte[] buffer = new byte[1024];” e não o “InputStream”…
O InputStream só indica um lugar da memória onde começa os dados, assim que você fechar o ResultSet, eles não estarão mais lá, não adianta o que você faça, então você precisa pegar estes dados, guardá-los num array (como você faria depois, de qualquer jeito), fechar o ResultSet e então transportar o array…
ze_kiefa
Ou seja, fazer a leitura em bytes diretamente no DAO e guardá-lo no bean, tornando-o independente do ResultSet?
L
Lao
Eu sugiro você alterar seu método setFoto() para ler do InputStream do banco de dados e armazená-lo no seu bean. Pode ser até em bytes como o Leandro disse ali, ou se quiser manter o mesmo InputStream, aí é com você.
ze_kiefa
publicclassPessoaDAO{// outros métodos omitidosprivatevoidpopulaBean(ResultSetrs,Pessoabean)throwsSQLException{bean.setId(rs.getInt("id"));bean.setNome(rs.getString("nome"));byte[]buffer=newbyte[1024];intbytesLidos=-1;while((bytesLidos=rs.getBinaryStream("foto").read(buffer,0,1024))>0){bean.setFoto(newByteArrayInputStream(buffer));}}}
Sugestão acatada (ainda tenho que testar, mas é só para dar um retorno!).
Se eu garantir que a foto tenha menos de 1 Mb (1024 bytes), eu posso trocar o while por if?
ze_kiefa
Uma pequena correção.
publicclassPessoaDAO{// outros métodos omitidosprivatevoidpopulaBean(ResultSetrs,Pessoabean)throwsSQLException{bean.setId(rs.getInt("id"));bean.setNome(rs.getString("nome"));InputStreamentrada=rs.getBinaryStream("foto");byte[]buffer=newbyte[1024];intbytesLidos=-1;while((bytesLidos=entrada.read(buffer,0,1024))>0){bean.setFoto(newByteArrayInputStream(buffer));}}}
Mas uma dúvida ainda remanescente: como eu guardo um array de bytes[] no InputStream (Pessoa.foto), pois da forma como está implementado acima, a minha foto sairá incompleta?
ze_kiefa
Versão final funcionando.
publicclassPessoaDAO{// outros métodos omitidosprivatevoidpopulaBean(ResultSetrs,Pessoabean)throwsSQLException{bean.setId(rs.getInt("id"));bean.setNome(rs.getString("nome"));InputStreamentrada=rs.getBinaryStream("foto");ByteArrayOutputStreambout=newByteArrayOutputStream();byte[]buffer=newbyte[1024];intbytesLidos=-1;while((bytesLidos=entrada.read(buffer,0,1024))>0){bout.write(buffer);}bean.setFoto(newByteArrayInputStream(bout.toByteArray()));}}ObrigadoLeandroeLao!