Exibir mensagem anterior :: Exibir próxima mensagem |
Autor |
Mensagem |
JCMF Profissional
Registrado: Quarta-Feira, 28 de Abril de 2010 Mensagens: 578 Localização: Recife, PE
|
Enviada: Sex Out 28, 2011 5:25 pm Assunto: Imagem com JSON via DataSnap? |
|
|
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 |
|
|
JCMF Profissional
Registrado: Quarta-Feira, 28 de Abril de 2010 Mensagens: 578 Localização: Recife, PE
|
Enviada: Sex Out 28, 2011 7:35 pm Assunto: Re: Imagem com JSON via DataSnap? |
|
|
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 |
|
|
andreano Novato
Registrado: Terça-Feira, 7 de Junho de 2005 Mensagens: 86
|
|
Voltar ao Topo |
|
|
andreano Novato
Registrado: Terça-Feira, 7 de Junho de 2005 Mensagens: 86
|
Enviada: Sáb Out 29, 2011 2:30 am Assunto: |
|
|
Outra possibilidade é usar TSTream em TImage na propriedade foto, desta forma você não precisaria criar um converter. |
|
Voltar ao Topo |
|
|
johnny-walker Moderador
Registrado: Sábado, 4 de Outubro de 2003 Mensagens: 10653 Localização: Contagem/MG - BRAZIL
|
Enviada: Dom Out 30, 2011 11:11 am Assunto: |
|
|
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 |
|
|
JCMF Profissional
Registrado: Quarta-Feira, 28 de Abril de 2010 Mensagens: 578 Localização: Recife, PE
|
Enviada: Seg Out 31, 2011 9:42 am Assunto: |
|
|
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 |
|
|
JCMF Profissional
Registrado: Quarta-Feira, 28 de Abril de 2010 Mensagens: 578 Localização: Recife, PE
|
Enviada: Seg Out 31, 2011 11:43 am Assunto: |
|
|
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 |
|
|
JCMF Profissional
Registrado: Quarta-Feira, 28 de Abril de 2010 Mensagens: 578 Localização: Recife, PE
|
Enviada: Seg Out 31, 2011 12:07 pm Assunto: |
|
|
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 |
|
|
JCMF Profissional
Registrado: Quarta-Feira, 28 de Abril de 2010 Mensagens: 578 Localização: Recife, PE
|
Enviada: Seg Out 31, 2011 1:00 pm Assunto: |
|
|
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 |
|
|
JCMF Profissional
Registrado: Quarta-Feira, 28 de Abril de 2010 Mensagens: 578 Localização: Recife, PE
|
Enviada: Seg Out 31, 2011 3:10 pm Assunto: |
|
|
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 |
|
|
ricardo.pascoal Novato
Registrado: Quarta-Feira, 5 de Mai de 2004 Mensagens: 11
|
Enviada: Sex Mai 10, 2013 5:55 pm Assunto: |
|
|
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 |
|
|
|