ActiveDelphi - Índice do Fórum ActiveDelphi
.: O site do programador Delphi! :.
 
 FAQFAQ   PesquisarPesquisar   MembrosMembros   GruposGrupos   RegistrarRegistrar 
 PerfilPerfil   Entrar e ver Mensagens ParticularesEntrar e ver Mensagens Particulares   EntrarEntrar 

Imagem com JSON via DataSnap?

 
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Delphi
Exibir mensagem anterior :: Exibir próxima mensagem  
Autor Mensagem
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sex Out 28, 2011 5:25 pm    Assunto: Imagem com JSON via DataSnap? Responder com Citação

Boa tarde amigos!

Alguém já tentou disponibilizar uma imagem tipo TBitmap, TJPEG ou até mesmo um TPicture com JSON via DataSnap?

Estou tentando fazer isso da seguinte forma: Uma classe que possui uma propriedade tipo TPicture que carrega essa imagem de uma base de dados qualquer:

Código:
strImagem := dataset.CreateBlobStream( dataset.FieldByName( 'imagem' ), bmRead );
jpgImagem := TJPEGImage.Create;

try

  jpgImagem.LoadFromStream( strImagem );
 
  // A propriedade Imagem é do tipo TPicture
  usuario.Imagem.Assign( jpgImagem );

finally

  jpgImagem.Free;
  strImagem.Free;

end;

No cliente, após recuperar o objeto usuário do servidor, estou tentando carregar essa imagem da seguinte forma:
Código:
imgFoto.Picture.Assign( usuario.Imagem );

Mas não acontece nada e aparentemente existe algum conteúdo na propriedade usuario.Imagem

Detalhe: Tudo isso, de servidor para cliente, com JSON utilizando o recurso de Marshall e Unmarshall. O retorno é um JSONValue

Alguma dica?
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sex Out 28, 2011 7:35 pm    Assunto: Re: Imagem com JSON via DataSnap? Responder com Citação

Detalhando o problema...

Na classe TUsuario, existe uma propriedade chamada de Imagem que é do tipo TJPEGImage.
Essa propriedade está declarada da seguinte forma:
Código:
property Imagem: TJPEGImage read FImagem write SetImagem;

O método SetImagem segue abaixo:
Código:
procedure TUsuario.SetImagem(const imagem: TJPEGImage);
begin

  FImagem.Assign( imagem );

end;

No método Create da classe, executo o seguinte código:
Código:
FImagem := TJPEGImage.Create;

Com isso, a implementação da classe está pronta e funcionando como será mostrado depois.

A rotina em questão realiza uma consulta no banco para achar um determinado usuário cadastrado (vamos subentender que ele achou o usuário na tabela) e cria um objeto TUsuario, preenchendo suas propriedades com os dados da consulta.
Isso é feito nesse código:
Código:
usuario.Id := adoQuery.FieldByName( 'id' ).AsInteger;
usuario.Nome := adoQuery.FieldByName( 'nome' ).AsString;
usuario.Login := adoQuery.FieldByName( 'login' ).AsString;
usuario.Senha := adoQuery.FieldByName( 'senha' ).AsString;
usuario.Email := adoQuery.FieldByName( 'email' ).AsString;
usuario.UltimoLogin := adoQuery.FieldByName( 'ultimo_login' ).AsString;
usuario.Administrador := adoQuery.FieldByName( 'administrador' ).AsBoolean;
usuario.RecebeMensagens := adoQuery.FieldByName( 'recebe_mensagens' ).AsBoolean;
usuario.ControlaClasse := adoQuery.FieldByName( 'controla_classe' ).AsBoolean;
usuario.AlteraSenha := adoQuery.FieldByName( 'altera_senha' ).AsBoolean;
usuario.IdPerfil := adoQuery.FieldByName( 'id_perfil' ).AsInteger;
usuario.LogAuditoria := adoQuery.FieldByName( 'log_auditoria' ).AsBoolean;
usuario.Bloqueado := adoQuery.FieldByName( 'bloqueado' ).AsBoolean;

// Definindo a imagem do usuário
strImagem := adoQuery.CreateBlobStream( adoQuery.FieldByName( 'imagem' ), bmRead );
jpgImagem := TJPEGImage.Create;

try

  jpgImagem.LoadFromStream( strImagem );
  usuario.Imagem := jpgImagem;

finally

  jpgImagem.Free;
  strImagem.Free;

end;

A partir daí, se eu colocar um TImage normal no formulário e executar o código abaixo, a imagem aparece com perfeição:
Código:
FormTeste.imgFoto.Picture.Assign( usuario.Imagem );

Oq prova que o conteúdo em "usuario.Imagem" está correto.

Agora vem a bronca: Tudo isso está sendo executado na aplicação servidor, que é onde transformo esse objeto usuario (do tipo TUsuario) para JSON para passá-lo para o cliente. O código está abaixo:
Código:
function TUsuario.ObjectToJSON(myObject: TUsuario): TJSONValue;
var
  marshal: TJSONMarshal;
begin

  if not Assigned( myObject ) then
    Exit( TJSONnull.Create );

  marshal := TJSONMarshal.Create;

  try
    Exit( marshal.Marshal( myObject ) );
  finally
    marshal.Free;
  end;

end;


Quando o cliente recebe esse objeto JSON, faço a conversão de volta para o tipo TUsuario com o código abaixo:
Código:
function TUsuario.JSONToObject(json: TJSONValue): TUsuario;
var
  unMarshal: TJSONUnMarshal;
begin

  if json is TJSONNull then
    Exit( nil );

  unMarshal := TJSONUnMarshal.Create;

  try
    Exit( TUsuario( unMarshal.Unmarshal( json ) ) );
  finally
    unMarshal.Free;
  end;

end;

Tudo aparentemente certo.

A partir daqui, acontece o problema... se tento executar o mesmo teste feito no servidor, ele dá um erro estranho e a imagem não aparece...
O simples código de testes na aplicação cliente que não funciona:
Código:
FormTesteCliente.imgFoto.Picture.Assign( usuario.Imagem );


Espero que todos possam entender o problema!
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
andreano
Novato
Novato


Registrado: Terça-Feira, 7 de Junho de 2005
Mensagens: 86

MensagemEnviada: Sáb Out 29, 2011 2:18 am    Assunto: Responder com Citação

Você precisar criar um conversor para o tipo imagem.

Da uma olhada neste post - http://blogs.embarcadero.com/adrian/2009/08/19/json-types-for-server-methods-in-datasnap-2010/
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
andreano
Novato
Novato


Registrado: Terça-Feira, 7 de Junho de 2005
Mensagens: 86

MensagemEnviada: Sáb Out 29, 2011 2:30 am    Assunto: Responder com Citação

Outra possibilidade é usar TSTream em TImage na propriedade foto, desta forma você não precisaria criar um converter.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
johnny-walker
Moderador
Moderador


Registrado: Sábado, 4 de Outubro de 2003
Mensagens: 10653
Localização: Contagem/MG - BRAZIL

MensagemEnviada: Dom Out 30, 2011 11:11 am    Assunto: Responder com Citação

Amigo, acredito que vc deverá trabalhar com o tipo Array do json para conseguir isto, dê uma pesquisada sobre, mas infelizmente é o tipo array que vc está procurando.

bye
_________________
P.O.W.E.R B.Y D.E.L.P.H.I
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Seg Out 31, 2011 9:42 am    Assunto: Responder com Citação

andreano escreveu:
Outra possibilidade é usar TSTream em TImage na propriedade foto, desta forma você não precisaria criar um converter.

Tentei utilizar o TStream, através do objeto TMemoryStream mas, dá o erro "JPEG Error #42" =(
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Seg Out 31, 2011 11:43 am    Assunto: Responder com Citação

johnny-walker escreveu:
Amigo, acredito que vc deverá trabalhar com o tipo Array do json para conseguir isto, dê uma pesquisada sobre, mas infelizmente é o tipo array que vc está procurando.

bye

Amigão...

Infelizmente o JSONArray não resolve meu problema pois ele armazena os tipos naturais JSON e o atributo em questão não é um tipo JSON padrão...
A classe é 99,99% convertida no cliente, o único erro é com relação ao tipo TJPEGImage que não é um tipo nativo JSON...

O Andreano deu a idéia de usar TStream que nada mais é do que binários, e por isso mesmo, suportado pelo JSON mas... não está dando certo.. =(
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Seg Out 31, 2011 12:07 pm    Assunto: Responder com Citação

Amigos, ainda não deu certo mas... estou meio que na metade da solução.

Alterei a classe TUsuario para salvar um TStream no lugar de um TJPEGImage. Do lado servidor, tento exibir o conteúdo da propriedade usuario.Imagem num TImage normal da seguinte forma:
Código:
    foto := TJPEGImage.Create;

    usuario.Imagem.Position := 0;
    foto.LoadFromStream( usuario.Imagem );

    FormServer.imgPlanoFundo.Picture.Assign( foto );

Funciona perfeitamente! A imagem é exibida.

O problema é quando passo esse objeto usuario via JSON para o cliente e tento exibir o conteúdo de usuario.Imagem, dá o seguinte erro:
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Seg Out 31, 2011 1:00 pm    Assunto: Responder com Citação

Novo teste amigos!

A classe TUsuario continua salvando a propriedade Imagem como um TStream.
No lado do servidor, criei um método chamado de GetImage e retornando um TStream.
Assinatura abaixo:
Código:
function GetImage( const id: Integer ): TStream;

Implementação abaixo:
Código:
function TServerModuleUsuario.GetImage(const id: Integer): TStream;
var
  adoQuery: TADOQuery;
begin

  result := nil;

  try

    builder := GetPreparedQuery( id );

    builder.Open;

    result := builder.CreateBlobStream( builder.FieldByName( 'imagem' ), bmRead );

    builder.Destroy( True );

  except
    result := nil;
  end;

end;


Pronto! Esse método está sendo disponibilizado para o cliente... e dessa vez, funfou com perfeição absoluta!

Moral da história: Quando tento converter o tipo TStream ou TJPEGImage para JSON e depois, de volta para o tipo de origem... ele simplesmente empanca e dá erro!

O JSON só converte os tipos primitivos do delphi e nada mais!
Como fazer para passar um objeto criado por mim e que possui um atributo complexo?
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Seg Out 31, 2011 3:10 pm    Assunto: Responder com Citação

Pessoal...

Não sei dizer se isso foi uma "solução" mas, só consegui passar o objeto do servidor para o cliente transformando o atributo Imagem em string.

Troquei a classe TMemoryStream por uma TStringStream e a coisa funcionou mais que demais!

Mas, e quando não for possível fazer um processo como esse? E todo o projeto DataSnap já pronto parado por conta de um único tipo?

Fiquei com medo agora viu!
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
ricardo.pascoal
Novato
Novato


Registrado: Quarta-Feira, 5 de Mai de 2004
Mensagens: 11

MensagemEnviada: Sex Mai 10, 2013 5:55 pm    Assunto: Responder com Citação

Olá JCMF !

Rapaz, também estou com esse mesmo problema ! Tenho um framework proprio e estou emperrado nesse ponto.

Chegou em alguma solução ?

Qualquer coisa em adiciona ai no skype : ricardo.pascoal

abraço
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
Mostrar os tópicos anteriores:   
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Delphi Todos os horários são GMT - 3 Horas
Página 1 de 1

 
Ir para:  
Enviar Mensagens Novas: Proibido.
Responder Tópicos Proibido
Editar Mensagens: Proibido.
Excluir Mensagens: Proibido.
Votar em Enquetes: Proibido.


Powered by phpBB © 2001, 2005 phpBB Group
Traduzido por: Suporte phpBB