Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Internet (https://www.clubdelphi.com/foros/forumdisplay.php?f=3)
-   -   Enviar y recibir imgenes por servicios web (https://www.clubdelphi.com/foros/showthread.php?t=85412)

jscubillos5 13-03-2014 21:17:01

Enviar y recibir imgenes por servicios web
 
Buen da comunidad, quisiera saber si alguno de ustedes sabe enviar y recibir imgenes por servicios web de Delphi??

Neftali [Germn.Estvez] 14-03-2014 17:01:51

Revisa este artculo y la segunda parte, a ver si es lo que necesitas.

jscubillos5 14-03-2014 17:32:20

Gracias
 
Hola Neftali, muchsimas gracias por tu ayuda, pero esto no es especficamente lo que necesito, he estado investigando, y recopilando informacin y la forma ms fcil de enviar imgenes por servicios web, es tomar la parte binaria de la imagen y transformarla a texto, ene ste caso estoy intentando hacer un demo, para lograrlo y actualmente tengo esto:

Tengo un formulario, en el cual solo tengo un control de imagen, un botn y un dialogo, en ele evento ONCLICK del boton tengo:

Cdigo Delphi [-]
procedure TForm1.ButtonTransformarImagenEnCorrienteClick(Sender: TObject);
var
  CorrienteArchivo: TFileStream;
  CorrienteEntexto: String;
begin
  // Si se ejecuta el dialogo
  if OpenDialogUPrincipal.Execute then
  begin
    try
      // Le asigno a la corriente el archivo abierto
      CorrienteArchivo:= TFileStream.Create(OpenDialogUPrincipal.FileName, fmOpenRead);
      try
        // Muestro la imagen en el control
        ImageControlUPrincipal.Bitmap.LoadFromStream(CorrienteArchivo);
        // Convierto mi corriente en texto
        CorrienteEntexto:= DeCorrienteaTexto(CorrienteArchivo);
        // Cargo el valor de CorrienteEntexto, a la propiedad TEXT del memo
        MemoUPrincipal.Text:= CorrienteEntexto;
      finally
        // Libero la corriente
        CorrienteArchivo.Free;
      end;
    except
      on E: Exception do
      begin
        // En caso de algn error
        raise Exception.Create(e.Message);
      end;
    end;
  end
  else
  begin
    raise Exception.Create('Error se debio haber ejecutado el dialogo.');
  end;
end;

La funcin DeCorrienteaTexto, tiene:

Cdigo Delphi [-]
function TForm1.DeCorrienteaTexto(Corriente: TStream): String;
var
  Temporal: TStringStream;
begin
  // Si la corriente es diferente de vacia
  if Corriente <> nil then
  begin
    // Creo mi corriente string termporal
    Temporal := TStringStream.Create('');
    try
      // Copio a mi corriente string la corriente desde la posicion 0
      Temporal.CopyFrom(Corriente, 0);
      // Le asigno al resultado el valor de mi corriente string, en la propiedad DataString
      Result := Temporal.DataString;
    finally
      Temporal.Free;
    end;
  end
  else
  begin
    Result := '';
  end;
end;

Ahora actualmente tengo solo un problema, todo el cdigo funciona, y carga los valores de forma correcta, pero cuando intento cargar el texto en el memo, el memo solo muestra hasta el primer espacio del archivo binario es decir:

Archivo binario original:

JFIF     &%"/ #'),,,150*5&+,)

 )$,)*,*,5))/))2)5,5),),)),))5./),),))),),,,,1,-),,+)  P"     9  ! 1AQ"aq2ѡBRb#3$r    $  !1A"Qa   ? gj{/'i*jquh\\F߸/Ѣuw5j~x/M EUtqsq'L֊Q
O?|v@*m;|n/{}#5#P/`:bcD"qL($
;lwT w ѱVӧ<3ybzyJ*
[?8hZ3߈uuf/@I RrPv'0Rj @бpW, afoMjK:Ś|D.KJI݌ j,Ãy>ʡ`T 51ڶҡG\vca ɽz jhHQ?cԞh)UPjE${`]@hH;yC
ܢ`~qb^/t~bHDاa~0~|i`EXtþ+]ش;:R3𐍙 -$r1~pvW*QSL5qN':V>So(oݱ_pZJ.-H<aP{<y)R.0RaM-h'Ar:V#KM9;hiDK7|TB Qؓ*p$;t“6+=,> UlIF,OXsnzt<3*fDD<"M> *0XXӿ ,*
4jE fuJ߳jR!y2o#^ؒ#l\ycr@>QZetV\K-#T
<
{ڹOUTOwi  r0pSz!Y.c0AbFSS*e_I#fX!Y55C)S `⵩YB}# ߋiP_c|1݊jzl6|+mc Z!L0LĹUe4ēn]zϖfE!J#1`dm8:gøp߃pCV\Dڢ*QgƟV4lO;1D x D@$Wnu789UM u
} ),*2pGfPC􂶝/Q#cuu2E'N2bf%@;ퟮ 0ϐ>9jPOb'am¡lHȾ 3 8;u!yx-n5xN.^7d4$*~x
lI!@)'Py×@:+.]wnfMbokio*rĆ x<#w/%BU&^ѵXœmsL40ym
p9.(UIaērb"2BE fߑKD*3$ ^7؜
u;sfP 9cP])ۧRJPFI MG?\W =Ŗ
F>LA? b*g~1] R+w3|kQs&TYYLt
;`VD̟X &l.i*Y"L_f!| *<IldzVtއ]0$
k$I qL8L(*1ᾐ _Ӗ(bj__˰e)%vk0i-7 !:I^q*i++(6V*g}RJ&$ 1jQv> UQ T$`c-ZTlL7* <Juo)eU4$DLy`.1Z d 䣟ն]uiT*Pu -xsp.#]KB9&>g& m]0WU*wye @ߙӯrM
:*țA<3,t'jS)U US$7 8w{mF:SPX /m
e ȥy.'nSSU*UfS!R uPA㗏7_hKJM*c9?h+)#$\e5Fe&]*m8W,gV*35MrBvk>S@N7e*Bu7}0+qb#*bS[!@,&f"Ty: ogk3~QII/O9b(G<g5j*Q5Rb]*9_LQ){
fJ\KW6Zט$=
y
UfY0ߐ;7`xi WգL1"wI7J<xBWPk|K0ܿ[~RyǶDS1j4j3+Rt#Ke˖sAU?үc\A)"@cLry|z,NJq(p0d :E-`<8qāj*B9zj $-^L>=Ͱ*r*]-4*+[ *U@!}N.dYZ̻eYu

Texto mostrado en el memo:



Y no se por que??

egostar 14-03-2014 17:50:18

Y si agregas un Seek() antes de pasarlo al Resut?

Cdigo Delphi [-]
      // Copio a mi corriente string la corriente desde la posicion 0
      Temporal.CopyFrom(Corriente, 0);

      Temporal.Seek(0,0); 

      // Le asigno al resultado el valor de mi corriente string, en la propiedad DataString
      Result := Temporal.DataString;

Saludos

jscubillos5 14-03-2014 19:29:15

Hola Egostar, gracias por tu ayuda, prob con la linea de cdigo, pero sigo obteniendo el mismo resultado.

jscubillos5 14-03-2014 20:24:44

Hola comunidad ya encontr la solucin a mi problema, tuve que crear una funcin adicional que pasa de texto a imagen, esta funcin me retorna un TStream:

Cdigo Delphi [-]
function TForm1.DeTextoaCorriente(Texto: String): TStream;
begin
  try
    // Se le asigna a la variable result el valor del texto ingresado, llamando al TString.Create.
    Result:= TStringStream.Create(Texto);
  except
    on E: Exception do
    begin
      // En caso de error
      raise Exception.Create(e.Message);
    end;
  end;
end;

Ya en la imagen en el boton agregue solo estas lineas:

Cdigo Delphi [-]
Corriente:= DeTextoaCorriente(CorrienteEntexto);
        ImageControlUPrincipalTransformada.Bitmap.LoadFromStream(Corriente);

roman 14-03-2014 20:28:40

Bueno, pero es que t no ests conviertiendo en texto tu imagen. La propiedad DataString del Stream simplemente coloca los datos del stream en un string pero este string sigue teniendo datos binarios. En Delphi, un string carga datos de cualquier tipo, no slo caracteres legibles.

Debes buscar alguna biblioteca que te codifique la imagen como texto como UUencode o Base64. Me imagino que los componentes Indy traen algo as puesto que es lo que se usa para transferir datos binarios atravs del correo electrnico.

// Saludos

jscubillos5 17-03-2014 14:20:47

Hola Roma gracias por tu ayuda y tienes toda la razn, busque un cdigo para codificar la imagen a base 64, me base en este hilo del foro: http://www.clubdelphi.com/foros/showthread.php?t=48924, implemente el cdigo, y cuando intento enviarlo por el servicio web obtengo el siguiente error:



El valor de la variable a la cual le aplico el base 64 es:



El cdigo actual que tengo es:

Cdigo Delphi [-]
procedure TFormPrincipal.ButtonEnviarImagenClick(Sender: TObject);
var
  //CorrienteArchivo: TFileStream;
  CorrienteEntexto: String;
  Corriente : TMemoryStream;
begin
  // Utilizo un dialogo para buscar la imagen
  if OpenDialogPrincipal.Execute then
  begin
    // Creo un Stream
    Corriente:= TMemoryStream.Create;
    try
      try
        // Cargo en la corriente la imagne
        Corriente.LoadFromFile(OpenDialogPrincipal.FileName);
        //  Cargo la imagen en el control visual del formulario
        ImageControlUPrincipal.Bitmap.LoadFromStream(Corriente);
        // Envio los datos a la clase base64 y cargo los resultados en CorrienteEntexto
        CorrienteEntexto:= BinToStr(Corriente.Memory, Corriente.Size);
        // Consumo el servicio enviado todos los datos
        ICorrientedeImagenes1.GetICorrientedeImagenes.GuardarImagen(AnsiUpperCase(ExtractFileExt(OpenDialogP  rincipal.FileName)), ExtractFileName(OpenDialogPrincipal.FileName), ExtractFilePath(OpenDialogPrincipal.FileName), CorrienteEntexto);
      finally
        // Libero la corriente o Stream
        Corriente.Free;
      end;
    except
      // En caso de error muestro
      on E: Exception do
      begin
        raise Exception.Create(e.Message);
      end;
    end;
  end
  else
  begin
    // Por si cierran el dialogo sin escojer una imagen
    raise Exception.Create('Atencin ha cerrado el buscador sin seleccionar ninguna imagen.');
  end;
end;

jscubillos5 17-03-2014 15:50:31

Respuesta
 
Hola, por fin despus de buscar y buscar, encontr, que el usuario Seoane, ofrece su unit, con solo cdigo, sin usar la API de Windows, no entiendo todava, el por que del error, tal vez falta de compatibilidad, o tal vez Windows modifico esa unidad para Windows 7, la verdad todos son supuestos, pero la solucin es usar la Uni de Seoane, sin utilizar las librerias de Windows, la unit esta: http://delphi.jmrds.com/?q=node/84. :cool:

escafandra 17-03-2014 17:57:52

Efectivamente la solucin es usar una codificacin Base64. Aqu tienes ms ejemplos.

Saludos.

junyandroid 15-02-2017 19:20:51

Enviar y recibir imgenes por servicios web
 
Ya que lo solucionaste.

Podas colgar el cdigo completo de ejemplo de delphi y del servicio web.

Muchas Gracias.

AgustinOrtu 15-02-2017 20:32:36

Hola junyandroid, bienvenido a Club Delphi

Quiza el codigo que se publico en el hilo pueda dar lugar a confusiones para alguien novato.

Las "imagenes" no son mas que un monton de caracteres (que no son mas que "bytes") con algun formato en particular. Luego hay componentes o bibliotecas que saben interpretarlo para que se pueda ver en pantalla. Pero no deja de ser un "string gigantesco".

Si tanto tu servidor como cliente son Delphi, la forma mas sencilla de trabajar es usando Streams, en la que basicamente estas trabajando al nivel "bytes". Datasnap es capaz de manejar descendientes de TStream sin que haya necesidad de intervenir ni hacer nada mas

El servidor expone metodos de este estilo: (escribo de memoria, se me puede escapar algun detalle la sintaxis)

Cdigo Delphi [-]
type
{$METHODINFO ON}
  TServer = class(TDataModule)
  public
    procedure RecibirImagen(Stream: TStream);
    function ObtenerImagen({ parametros }): TStream;
  end;
{$METHODINFO OFF}


procedure TServer.RecibirImagen(Stream: TStream);
begin
  Stream.Position := 0;
 // utilizar el parametro Stream para lo que haga falta
end;

function TServer.ObtenerImagen(/*parametros*/): TStream;
begin
  { inicializar Result, es decir, crear algun descendiente de TStream. En este caso uso TFileStream }
  Result := TFileStream.Create(RutaImagen, fmOpen or fmRead);
end;

El cliente (ClientMethods1 es la clase proxy que te genera datasnap)

Cdigo Delphi [-]
procedure EnviarImagen;
var
  Stream: TStream;
begin
  // desde un archivo en disco local
  Stream := TFileStream.Create(RutaImagen, fmOpen or fmRead);
  try
    ClientMethods1.RecibirImagen(Stream);
  finally
    Stream.Free; {*}
  end;

  // desde un componente TImage
  Stream := TMemoryStream.Create;
  try
    Image1.SaveToStream(Stream);
    ClientMethods1.RecibirImagen(Stream);
  finally
    Stream.Free; {*}
  end;
end;

procedure PedirImagen;
var
  Stream: TStream;
begin
  Stream := ClientMethods1.PedirImagen({ parametros });
  try
    Stream.Position := 0;
    // cargar en un TImage
    Image1.LoadFromStream(Stream);

    // grabar a disco
    Stream.SaveToFile(RutaArchivo);
  finally
    Stream.Free; {*}
  end;
end;

{*}: No recuerdo exactamente pero es posible que Datasnap se haga cargo del manejo de memoria de los objetos que pasan a traves del proxy. En ese caso los bloques try-finally sobran y el Free no solo no es necesario sino que podria generar errores.

En realidad no se porque siempre hubo tanto rollo con el base64. Se ha convertido en una suerte de "estandar" cuando en realidad no tiene demasiadas ventajas (la codificacion lleva tiempo, se incrementa el tamao del stream adicional..). El unico caso en que usaria base64 es si estoy comunicandome con un webservice que ya este implementado asi y no pueda cambiar


La franja horaria es GMT +2. Ahora son las 17:26:43.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traduccin al castellano por el equipo de moderadores del Club Delphi