Ir al contenido



Foto

Guardando Imagenes a BD desde un record


  • Por favor identifícate para responder
8 respuestas en este tema

#1 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.409 mensajes
  • LocationRepública Dominicana

Escrito 28 abril 2017 - 05:42

Amigos, estoy tniendo problemas para guardar imágenes a la BD desde un record, es el siguiente:


delphi
  1. TVMEFotos = record
  2. VEHId: Integer;
  3. Area: String;
  4. Description: String;
  5. Extension: String;
  6. Indice: Integer;
  7. Imagen: TJPEGImage;
  8. public
  9. constructor Create(const AImage: String);
  10. end;

Este es el constructor:


delphi
  1. constructor TVMEFotos.Create(const AImage: String);
  2. begin
  3. //inherited create;
  4. Imagen := TJPEGImage.Create;
  5. Imagen.LoadFromFile(AImage);
  6. end;

Los datos de las imágenes las guardo en una lista TList<TVMEFotos>, así es como intento guardar los datos hacia la BD:


delphi
  1. procedure TVME.saveFotos(AId: Integer; ARecList: TList<TVMEFotos>);
  2. var Save: TFDQuery;
  3. i: Integer;
  4. begin
  5. Save := TFDQuery.Create(nil);
  6. Save.Connection := Datos.dbDatos;
  7. Save.SQL.Clear;
  8. Save.SQL.Add('INSERT INTO IMAGENES(FROM_ID,PICTURE,AREA,DESCRIPCION,EXTENSION) VALUES(:ID,:PIC,:AREA,:DESC,:EXT)');
  9. try
  10. for i := 0 to ARecList.Count -1 do begin
  11.  
  12. Save.ParamByName('ID').AsInteger := AId;
  13. Save.ParamByName('PIC').Assign(ARecList.Items[i].Imagen);
  14. Save.ParamByName('AREA').AsString := ARecList.Items[i].Area;
  15. Save.ParamByName('DESC').AsString := ARecList.Items[i].Description;
  16. Save.ParamByName('EXT').AsString := ARecList.Items[i].Extension;
  17.  
  18. try
  19. Save.ExecSQL;
  20. except
  21. on E:Exception do begin
  22. Datos.dbDatos.Rollback;
  23. MessageDLG(E.Message + ' en SaveFotos()',mtError,[mbOk],0);
  24. end;
  25. on E:EFDDBEngineException do begin
  26. Datos.dbDatos.Rollback;
  27. MessageDLG(E.Message + ' en saveFotos()',mtError,[mbOk],0);
  28. end else begin
  29. Datos.dbDatos.Rollback;
  30. raise Exception.Create('Hubo un problema al guardar las imágenes!');
  31. end;
  32. end; //Try except
  33. end; //for i
  34. finally
  35. Save.Free;
  36. end;
  37. end;

Pero al guardar me marca el siguiente error:

 

---------------------------
Debugger Exception Notification
---------------------------
Project SisAuto.exe raised exception class $C0000005 with message 'access violation at 0x00406d5b: write of address 0x00000008'.
---------------------------
Break   Continue   Help   
---------------------------

 

Y me marca esta línea en el depurador:

 

        FISTP   QWORD PTR [EDX+ECX]

 

 

Así que no entiendo pues.


  • 0

#2 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 28 abril 2017 - 06:29

Creo que hace falta depurar mas. Que pasa si pones un breakpoint en ese proceso y lo ejecutas paso a paso? 


  • 0

#3 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.409 mensajes
  • LocationRepública Dominicana

Escrito 29 abril 2017 - 08:28

El problema está en el parámetro de la imagen en la consulta:


delphi
  1. Save.ParamByName('PIC').Assign(ARecList.Items[i].Imagen);

Porque lo quité y sí guarda las demás informaciones, lo extraño es que muestro las imágenes en un TImage sin problemas, ¿hay alguna otra manera de guardar las imágenes a la BD?


  • 0

#4 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 29 abril 2017 - 10:43

Yo siempre utilizo Streams para guardar imagenes, archivos, etc

 

En un principio la forma que comentas vos "deberia" funcionar (*), ya que buscando por la web encontre varias fuentes que la utilizan.. pero son algo antiguas, ninguna en FireDAC

 

En FireDAC yo usaria alguna de estas alternativas: http://docwiki.embar...ming_in_FireDAC

 

* Asumiendo que no haya ningun nil, y que tanto el objeto parametro como imagen sean instancias correctamente inicializadas obvio


  • 1

#5 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 528 mensajes
  • LocationCali, Colombia

Escrito 02 mayo 2017 - 11:18

Definitivamente la mejor opción es utilizar streams, 

 

si es una consulta

 

    Query.Edit;

    TBlobField(Query.FieldByName('foto')).AsBlob.LoadFromStream(Stream)

    Query.Post;

 

Si es un insert como es tu caso, sería igual, solamente que en lugar de un campo, se utiliza el parámetro.

 

Saludos.


  • 1

#6 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.409 mensajes
  • LocationRepública Dominicana

Escrito 02 mayo 2017 - 05:12

Saludos GHenriquez hice lo siguiente:


delphi
  1. procedure TVME.saveFotos(AId: Integer; ARecList: TList<TVMEFotos>);
  2. var Save: TFDQuery;
  3. i: Integer;
  4. AStream: TMemoryStream;
  5. begin
  6. Save := TFDQuery.Create(nil);
  7. Save.Connection := Datos.dbDatos;
  8. Save.SQL.Clear;
  9. Save.SQL.Add('INSERT INTO IMAGENES(FROM_ID,PICTURE,AREA,DESCRIPCION,EXTENSION) VALUES(:ID,:PIC,:AREA,:DESC,:EXT)');
  10. try
  11. for i := 0 to ARecList.Count -1 do begin
  12.  
  13. AStream := TMemoryStream.Create;
  14. try
  15. ARecList.Items[i].Imagen.SaveToStream(AStream);
  16.  
  17. Save.ParamByName('ID').AsInteger := AId;
  18. TBlobField(Save.ParamByName('PIC')).LoadFromStream(AStream);
  19. Save.ParamByName('AREA').AsString := ARecList.Items[i].Area;
  20. Save.ParamByName('DESC').AsString := ARecList.Items[i].Description;
  21. Save.ParamByName('EXT').AsString := ARecList.Items[i].Extension;
  22.  
  23. try
  24. Save.ExecSQL;
  25. except
  26. on E:Exception do begin
  27. Datos.dbDatos.Rollback;
  28. MessageDLG(E.Message + ' en SaveFotos()',mtError,[mbOk],0);
  29. end;
  30. on E:EFDDBEngineException do begin
  31. Datos.dbDatos.Rollback;
  32. MessageDLG(E.Message + ' en saveFotos()',mtError,[mbOk],0);
  33. end else begin
  34. Datos.dbDatos.Rollback;
  35. raise Exception.Create('Hubo un problema al guardar las imágenes!');
  36. end;
  37. Exit;
  38. end; //Try except
  39. finally
  40. AStream.Free;
  41. end;
  42. end; //for i
  43. finally
  44. Save.Free;
  45. end;
  46. end;

Pero me marca error en la linea resaltada:


delphi
  1. procedure TBlobField.LoadFromStream(Stream: TStream);
  2. var
  3. LStream: TStream;
  4. begin
  5. LStream := DataSet.CreateBlobStream(Self, bmWrite);
  6. try
  7. LStream.CopyFrom(Stream, 0);
  8. finally
  9. LStream.Free;
  10. end;
  11. end;
  12.  

Saludos.


  • 0

#7 Agustin Ortu

Agustin Ortu

    Advanced Member

  • Moderadores
  • PipPipPip
  • 831 mensajes
  • LocationArgentina

Escrito 02 mayo 2017 - 05:20

Y que error te marca? A mi me da la sensacion de que el casteo forzado a TBlobStream es el culpable


  • 0

#8 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.409 mensajes
  • LocationRepública Dominicana

Escrito 02 mayo 2017 - 06:50

Y que error te marca? A mi me da la sensacion de que el casteo forzado a TBlobStream es el culpable

 

Pues de exception 0x0000000 y queda en la línea resaltada del código anterior, pude resolverlo de la siguiente manera, no sé qué tan eficiente puede ser, pero me sirvió:


delphi
  1. procedure TVME.saveFotos(AId: Integer; ARecList: TList<TVMEFotos>);
  2. var Save: TFDQuery;
  3. i: Integer;
  4. begin
  5. Save := TFDQuery.Create(nil);
  6. try
  7. Save.Connection := Datos.dbDatos;
  8. Save.SQL.Clear;
  9. Save.SQL.Add('SELECT FROM_ID,PICTURE,AREA,DESCRIPCION,EXTENSION FROM IMAGENES WHERE FROM_ID = 0 AND AREA = ' + QuotedStr('vme'));
  10. try
  11. Save.Open;
  12.  
  13. if Save.IsEmpty then begin
  14. for i := 0 to ARecList.Count -1 do begin
  15. Save.Append;
  16. Save.FieldByName('FROM_ID').AsInteger := AId;
  17. TBlobField(Save.FieldByName('PICTURE')).Assign(ARecList.Items[i].Imagen);
  18. Save.FieldByName('AREA').AsString := ARecList.Items[i].Area;
  19. Save.FieldByName('DESCRIPCION').AsString := ARecList.Items[i].Description;
  20. Save.FieldByName('EXTENSION').AsString := ARecList.Items[i].Extension;
  21. Save.Post;
  22. end;
  23. end;
  24. except
  25. Datos.dbDatos.Rollback;
  26. raise Exception.Create('Hubo un problema al grabar las imágenes en SaveFoto()');
  27. Exit;
  28. end;
  29. finally
  30. Save.Free;
  31. end;
  32. end;

Saludos.


  • 0

#9 genriquez

genriquez

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 528 mensajes
  • LocationCali, Colombia

Escrito 04 mayo 2017 - 01:56

Lamentablemente ahora solo tengo instalado firedac y no he podido hacer pruebas con los otros drivers

no se si tengas esta opción.

 

 

Var
  Stream : TMemoryStream;
begin
   Stream := TMemoryStream.Create;
   Stream.LoadFromFile('d:\temp\foto.jpg');
   Stream.Position := 0;  //Importante regresar el puntero al comienzo del archivo
 
 
   Query.Close;
   Query.SQL.Clear;
   Query.SQL.Add('INSERT INTO public.fotos(');
   Query.SQL.Add(' id, foto)');
   Query.SQL.Add(' VALUES (:Id, :Foto)');
 
   Query.Params.ParamByName('Foto').LoadFromStream(Stream, ftBlob);
   Query.Params.ParamByName('Id').AsInteger := 1;
 
   Query.ExecSQL;
 

End;


  • 0