Повреждение данных при записи blob поля в MySQL

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Повреждение данных при записи blob поля в MySQL

Сообщение Lekur » 18.09.2020 19:57:41

Добрый день.

Возникла проблема при попытке записи JPEG файла в blob поле MySQL в Лазарусе 2.0.6. под Windows 7.
Собственно запись данных в blob поле проходит, но данные приходят искаженные и по виду перекодированы.
Вот что должно быть:
яШяа JFIF    яЫ C  

 $.' ",#(7),01444'9=82<.342яЫ C 

Получаю это:
???? JFIF    ?? C  

 $.' ",#(7),01444'9=82<.342?? C 

Вроде явно указан тип ftBlob , двоичные данные, но нет где то их по пути перекодирует.
База данных старинная и проверена временем, фото от туда читаются в Лазарусе без проблем.
Текстовые поля также.
Пол дня сидел в поисковиках, но не нашел даже намека на решение проблемы.

Использую компоненты :
MySQL57Connection1: TMySQL57Connection;
SQLQuery1: TSQLQuery;
SQLTransaction1: TSQLTransaction;

код функции:
function TForm1.SavePhoto(uk: integer): boolean;
begin
Result:=False;
SQLTransaction1.Active:=False;
SQLQuery1.Clear;
SQLQuery1.SQL.Text:='update personal set photo =:BLOB_PHOTO where id = '+#39+Persons[uk].sID+#39+';';
SQLQuery1.ParamByName('BLOB_PHOTO').LoadFromFile('Photo.jpg',ftBlob);
try
SQLTransaction1.Active:=True;
except
//memo1.Lines.Add('Ошибка создания транзакции');
exit;
end;

SQLQuery1.ExecSQL;
result := SQLQuery1.RowsAffected >= -1;
if result then
SQLTransaction1.Commit
else
begin
SQLTransaction1.Rollback;
result := false;
end;

end;
Lekur
незнакомец
 
Сообщения: 2
Зарегистрирован: 18.09.2020 19:07:56

Re: Повреждение данных при записи blob поля в MySQL

Сообщение Vlad04 » 20.09.2020 06:41:18

Я решал аналогичную задачу используя набор компонентов, идущих с Lazarus, Zeos Access. В этом наборе есть класс TBlobStream, который осуществляет корректную запись/чтение blob-полей.

Код: Выделить всё
var
      BlStream : TStream;
      MyBitmap : TBitmap;
begin
...
      BlStream := CreateBlobStream(FieldByName('PASS_COPY'),bmWrite) ;
      MyBitmap.SaveToStream(BlStream) ;
      BlStream.Free ;
...
end;
Аватара пользователя
Vlad04
новенький
 
Сообщения: 78
Зарегистрирован: 11.12.2007 21:11:19
Откуда: Караганда. Казахстан

Re: Повреждение данных при записи blob поля в MySQL

Сообщение olegy » 20.09.2020 23:07:47

Lekur писал(а):Вроде явно указан тип ftBlob , двоичные данные, но нет где то их по пути перекодирует.

Скорее Blob поле открывается TStringStream и обрабатывается как String значение, отсюда Char "?" вместо Byte $XX.
Почему так? наверно есть поля Text которые по сути Blob-ы, раз нужно вывести в DBGrid - то выводится дефолтно как String
Поэтому надо работать через TStream(TStreamMemory/TSreamFile ..)
olegy
незнакомец
 
Сообщения: 6
Зарегистрирован: 05.12.2015 18:35:07

Re: Повреждение данных при записи blob поля в MySQL

Сообщение Vlad04 » 21.09.2020 07:26:44

Если Blob-поле обрабатывается как String, то попробуйте использовать quoted string. В модуле sysutils есть соответствующая функция
Код: Выделить всё
function QuotedStr(

  const S: string

):string;
Аватара пользователя
Vlad04
новенький
 
Сообщения: 78
Зарегистрирован: 11.12.2007 21:11:19
Откуда: Караганда. Казахстан

Re: Повреждение данных при записи blob поля в MySQL

Сообщение Lekur » 21.09.2020 13:15:58

Использование TStringStream не помогло , результат тот же. Похоже как и чем положены данные в blob SQLQuery не важно, при транзакции они по любому воспринимаются как текстовые и перекодируются. С просмотром данных проблем нет, то что пишет в базу я смотрю HeidiSQL.
Переходить на другие компоненты, возможно выход, но уже часть проекта на родных компонентах и довольно много, есть смысл ещё покапать.
Полагаю копать надо в сторону параметров ftGraphic и возможно исходников SQLQuery:
SQLQuery1.ParamByName('BLOB_PHOTO').LoadFromStream(tMs , ftBlob); //Портит данные
SQLQuery1.ParamByName('BLOB_PHOTO').LoadFromStream(tMs , ftMemo); //Портит данные
SQLQuery1.ParamByName('BLOB_PHOTO').LoadFromStream(tMs , ftGraphic); //Ругается на формат данных

var
tMs:TMemoryStream;
tSs:TStringStream;
begin
Result:=False;
Image1.Picture.LoadFromFile('Photo.jpg');
try
tMs:=TMemoryStream.Create;
tsS:=TStringStream.Create('');
tMs.LoadFromFile('Photo.jpg');
tMs.Position:=0;
tsS.CopyFrom(tMs,tMs.Size);

SQLQuery1.SQL.Text:='update personal set photo =:BLOB_PHOTO where id = '+#39+sID+#39+';';
SQLQuery1.ParamByName('BLOB_PHOTO').asBlob := tsS.DataString;
SQLQuery1.ExecSQL;
SQLTransaction1.Commit;

Добавлено спустя 5 часов 41 минуту 49 секунд:
Написал проверочную функцию на ZeosLib. В таком виде все работает корректно, пишет в базу правильно.
Вопрос, в чем косяк в стандартных компонентах остался. Я пробовал откатится на старые dll, со старыми компонентами 5.5. но не помогло.
В ZConnection есть по умолчанию отключенная опция AutoEncodingString, проверять не стал.

function TForm1.PhotoToSCUD(uk: integer): boolean;
var
tMs:TMemoryStream;
begin
Result:=False;
Image1.Picture.LoadFromFile('Photo.jpg');
try
tMs:=TMemoryStream.Create;
tMs.LoadFromFile('Photo.jpg');
tMs.Position:=0;
ZQuery2.SQL.clear;
Zconnection1.AutoCommit:=false;
ZQuery2.SQL.Text:='update personal set photo =:BLOB_PHOTO where id = '+#39+'3c17dbd2-a6fc-11e0-b5e4-0050568e4f6c'+#39+';';
ZQuery2.ParamByName('BLOB_PHOTO').SetBlobData(tMs.Memory,tMs.Size);
ZQuery2.execsql;
Zconnection1.Commit;
ZConnection1.AutoCommit:=true;
finally
tMs.Free;
end;

end;
Lekur
незнакомец
 
Сообщения: 2
Зарегистрирован: 18.09.2020 19:07:56

Re: Повреждение данных при записи blob поля в MySQL

Сообщение DYUMON » 22.09.2020 07:56:35

Старанно конечно. Компоненты по умполчанию не без греха конечно, но работают вроде.
Ради теста не поленился накатал такой код.
Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, mysql56conn, sqldb, Forms, Controls, Graphics, Dialogs,
  StdCtrls, db;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    MS: TMySQL56Connection;
    OpenDialog1: TOpenDialog;
    SQLQuery1: TSQLQuery;
    SQLTransaction1: TSQLTransaction;
    procedure Button1Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  if OpenDialog1.Execute then
  begin
  ms.HostName:='localhost';
  ms.DatabaseName:='test';
  ms.UserName:='еуые';
  ms.Password:='еуые';
  ms.Port:=3306;
  ms.Connected:=true;
  SQLQuery1.SQL.Text:='INSERT INTO table1(myblob) VALUES (:myblob);';
  SQLQuery1.ParamByName('myblob').LoadFromFile(OpenDialog1.FileName, ftBlob);
  SQLQuery1.ExecSQL;
  ms.Transaction.Commit;

  end;
end;

end.
                         


Загрузил картинку , выгрузил, ни байта не изменилось.

Добавлено спустя 1 минуту 41 секунду:
Структура таблицы
Код: Выделить всё
CREATE TABLE test.table1 (
  id int(11) NOT NULL AUTO_INCREMENT,
  myblob longblob DEFAULT NULL,
  PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET latin1,
COLLATE latin1_swedish_ci;
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Аватара пользователя
DYUMON
постоялец
 
Сообщения: 234
Зарегистрирован: 11.03.2009 13:32:54


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: S_Gur и гости: 40

Рейтинг@Mail.ru