(Решено) Картинку в блоб-поле
Модератор: Модераторы
- GAMER
- энтузиаст
- Сообщения: 627
- Зарегистрирован: 06.08.2008 13:41:07
- Откуда: Ужгород-Днепр, Украина
- Контактная информация:
(Решено) Картинку в блоб-поле
Тема писана-переписана. Но.
Я работаю с MySQL напрямую, не используя никаких компонент. Все запросы отправляются строкой. По-этому те ответы, что я нашел, мне не подходят.
Как TImage преобразовать в AnsiString или PChar? Пробовал через TStream, но что-то не получается.
Я работаю с MySQL напрямую, не используя никаких компонент. Все запросы отправляются строкой. По-этому те ответы, что я нашел, мне не подходят.
Как TImage преобразовать в AnsiString или PChar? Пробовал через TStream, но что-то не получается.
Последний раз редактировалось GAMER 11.12.2010 14:33:56, всего редактировалось 1 раз.
- coyot.rush
- постоялец
- Сообщения: 309
- Зарегистрирован: 14.08.2009 08:59:48
Может через Base64 http://ru.wikipedia.org/wiki/Base64 если все хранить AnsiString
GAMER писал(а):Как TImage преобразовать в AnsiString или PChar?
Код: Выделить всё
var Buff: PChar;
Tmp: TMemoryStream;
...
Image.SaveToStream(Tmp);
...
GetMem(Buff^, Tmp.Size);
Tmp.Position:=0;
Tmp.Write(Buf^, Tmp.Size);
...
Что-то в этом роде.
Не только в PChar, но и в string можно пихать нулевые байты, тем более, что сейчас там utf-8...
В случае с PChar не забудьте FreeMem.
В случае с PChar не забудьте FreeMem.
Какие строки?
Вы через API с MySQL работаете?
Нельзя-ли показать заголовок функции, которая апдейтит блоб?
Что-то я подозреваю, что что-то не так...
Вы через API с MySQL работаете?
Нельзя-ли показать заголовок функции, которая апдейтит блоб?
Что-то я подозреваю, что что-то не так...
- GAMER
- энтузиаст
- Сообщения: 627
- Зарегистрирован: 06.08.2008 13:41:07
- Откуда: Ужгород-Днепр, Украина
- Контактная информация:
Код: Выделить всё
Function QuerryP(Const MySock : PMYSQL; Const SelStr: PChar; Out MySQLErrMsg : AnsiString): boolean;
Begin
Result := True;
if (mysql_query(MySock,SelStr) > 0) then
begin
MySQLErrMsg := 'Query failed. '+ mysql_error(MySock);
Result := False;
exit;
end;
End;Добавлено спустя 6 минут 19 секунд:
Как правильно к одной строке PChar добавить другую строку PChar, если и там и там есть нулевые байты?
Нужно сформирвоать строку типа 'insert into foto set unsprava=1, foto=CAST("'+Buff+' as binary)'
mysql_escape_string() - экранирует специальные символы в строке, т.е. нечитабельные в запросе.
GAMER писал(а):Как правильно к одной строке PChar добавить другую строку PChar, если и там и там есть нулевые байты?
Код: Выделить всё
StrCat(PChar1, PChar2);И посмотрите getBlobHandle
Вообще, я привык к тому как в FireBird.
Поэтому, замолкаю - тут я не большой знаток.
Вообще, я привык к тому как в FireBird.
Поэтому, замолкаю - тут я не большой знаток.
- GAMER
- энтузиаст
- Сообщения: 627
- Зарегистрирован: 06.08.2008 13:41:07
- Откуда: Ужгород-Днепр, Украина
- Контактная информация:
Что-то у меня strcat криво работает, если данные бинарные. Или это watch-окно криво показывает?
Добавлено спустя 5 часов 46 минут 22 секунды:
mysql_real_escape_string немного помогает, но проблема в том, что строки работают в UTF8, и на некоторых байтах становится вопросительный знак, на что собственно и ругается майСКЛ.
Добавлено спустя 5 часов 46 минут 22 секунды:
mysql_real_escape_string немного помогает, но проблема в том, что строки работают в UTF8, и на некоторых байтах становится вопросительный знак, на что собственно и ругается майСКЛ.
- GAMER
- энтузиаст
- Сообщения: 627
- Зарегистрирован: 06.08.2008 13:41:07
- Откуда: Ужгород-Днепр, Украина
- Контактная информация:
И так, получилось
Может кому-то пригодится.
Сначала о граблях.
1. Основные грабли - это нулевые символы в данных. При работе с PChar, AnsiString получаем кучу гемора.
2. Нужно быть очень аккуратными при работе с MemoryStreamN.Write
3. Нужно аккуратно использовать mysql_real_escape_string. Оно преобразовывает все, в том числе и те кавычки, которые не нужно було
Долго с этим возился 
4. При анализе данных в watch-окне, в строках фигурируют вопросительные знаки. Это все UTF8. Нужно побайтно просматривать.
Что нужно (желательно) использовать.
1. В запросах делаем CAST("...'" as binary)
2. Служебные символы Мускуля обходим с помощью mysql_real_escape_string, но аккуратно.
3. Размер вывода получаем через mysql_fetch_lengths(PResult) (другие функции обрезают длину по нулевому символу.)
Примеры наведу позже, после глобальной чистки кода.
Добавлено спустя 6 часов 10 минут 48 секунд:
Re: (Решено) Картинку в блоб-поле
Обещаный код:
Подпрограмма записи в блоб-поле:
Подпрограмма форимрования запроса для записи:
Подпрограмма чтения блоб-поля:
Подпрограмма формирования запроса и вставки картинки:
Сначала о граблях.
1. Основные грабли - это нулевые символы в данных. При работе с PChar, AnsiString получаем кучу гемора.
2. Нужно быть очень аккуратными при работе с MemoryStreamN.Write
3. Нужно аккуратно использовать mysql_real_escape_string. Оно преобразовывает все, в том числе и те кавычки, которые не нужно було
4. При анализе данных в watch-окне, в строках фигурируют вопросительные знаки. Это все UTF8. Нужно побайтно просматривать.
Что нужно (желательно) использовать.
1. В запросах делаем CAST("...'" as binary)
2. Служебные символы Мускуля обходим с помощью mysql_real_escape_string, но аккуратно.
3. Размер вывода получаем через mysql_fetch_lengths(PResult) (другие функции обрезают длину по нулевому символу.)
Примеры наведу позже, после глобальной чистки кода.
Добавлено спустя 6 часов 10 минут 48 секунд:
Re: (Решено) Картинку в блоб-поле
Обещаный код:
Подпрограмма записи в блоб-поле:
Код: Выделить всё
Function QuerryP(Const MySock : PMYSQL; Const SelStr: PChar; Const len: longint; Out MySQLErrMsg : AnsiString): boolean;
Begin
Result := True;
if (mysql_real_query(MySock,SelStr, len) <> 0) then
begin
MySQLErrMsg := 'Query failed. '+ mysql_error(MySock);
Result := False;
exit;
end;
End; Подпрограмма форимрования запроса для записи:
Код: Выделить всё
procedure TFrmWebcam.Button2Click(Sender: TObject);
const S1='insert into foto set unsprava=1, foto=CAST("';
S2='" as binary)';
var
Stream: TMemoryStream;
w1, w2: Pchar;
begin
// Image1.Picture.Jpeg.SaveToFile('test.jpg');
Stream := TMemoryStream.Create;
// Image1.Picture.Jpeg.SetSize(10,10);
Image1.Picture.Jpeg.SaveToStream(Stream); // Сохраняем Jpeg-картинку в поток
Stream.Position:=0;
GetMem(w1, Stream.Size);
Stream.Read(w1[0], Stream.Size); // Читаем с потока в переменную w1
GetMem(w2, 2*Stream.Size);
mysql_real_escape_string(MySockW, w2, w1, Stream.Size); //Делаем читабельную для Мускуля строку
Stream.Free;
if not QuerryP(MySockW, Pchar(s1+w2+s2), Length(s1+w2+s2), ErrMsg) then ShowMessage(ErrMsg);
Freemem(w1);Freemem(w2);
end; Подпрограмма чтения блоб-поля:
Код: Выделить всё
Function SelectToMemoryStream(Const Mysock: PMYSQL; Const SelStr: AnsiString; Var MemoryStreamN: TMemoryStream; Out VMySQLErrMsg : AnsiString): boolean;
Var FieldCount: Integer;
PCurrentRow: {$IFDEF FPC}MySQL_Row{$ELSE}PMySQL_Row{$ENDIF};
PResult: Pointer;
RecordCount: Integer;
LenArray: PDWord;
Begin
Result := True;
if (mysql_query(MySock,PChar(SelStr)) > 0) then
begin
VMySQLErrMsg := 'Ошибка запроса. '+ mysql_error(MySock);
Result := False;
exit;
end;
PResult:= MySQL_Use_Result(MySock); {Can be called for select and none-select. Returns nil if storing failed or if query was none-select}
if PResult = nil then
begin
if MySQL_Field_Count(MySock) = 0 then {It was a none-select}
begin
VMySQLErrMsg := 'Запрос не возвратил поля. '+chr(10)+chr(13)+
'Обработано '+IntToStr(MySQL_Affected_Rows(MySock))+' записей.';
Result := False;
exit;
end
else {It was a select query, but an error has occured}
begin
VMySQLErrMsg := 'Ошибка запроса. '+ mysql_error(MySock);
Result := False;
exit;
end;
end;
// else Result is not null - receiving data
try
// Fields count receiving
FieldCount:= MySQL_Num_Fields(PResult);
if (FieldCount=0) or (FieldCount>1) then
begin
VMySQLErrMsg := 'Запрос не возвратил поля либо полей больше 1';
Result := False;
exit;
end;
// Record data receiving
RecordCount := 0;
PCurrentRow:= MySQL_Fetch_Row(PResult);
LenArray:=mysql_fetch_lengths(PResult);
while PCurrentRow <> nil do
begin
Inc(RecordCount);
MemoryStreamN.Position:=0;
MemoryStreamN.Write(PCurrentRow[0][0], LenArray[0]);
PCurrentRow:= MySQL_Fetch_Row(PResult);
end;
finally
MySQL_Free_Result(PResult);
PResult:=nil;
PCurrentRow:=nil;
end;
End; Подпрограмма формирования запроса и вставки картинки:
Код: Выделить всё
procedure TFrmWebcam.Button3Click(Sender: TObject);
Var Stream: TMemoryStream;
Begin
Stream := TMemoryStream.Create;
if not SelectToMemoryStream(MySockW,
'select CAST(foto as binary) from foto',
Stream, ErrMsg) then
ShowMessage(ErrMsg)
else
begin
Stream.Position:=0;
Image1.Picture.Jpeg.LoadFromStream(Stream);
end;
Stream.Free;
End; 