UDF, записывающая картинку из файла в BLOB
Модератор: kdv
UDF, записывающая картинку из файла в BLOB
Здравствуйте. Помогите, пожалуйта, разобраться с моей проблемой.
Использую Firebird 2.0+Delphi 6. Есть таблица, в которой хранятся пути к графическим файлам. В клиентском приложении требуется по имени файла получить картинку и вывести её пользователю. Требуется написать UDF, которой передаётся имя файла, она переписывает содержимое файла в переменную типа BLOB и возвращает её. Проблема в том, что мне никак не удаётся реализовать такую функцию.
Использую Firebird 2.0+Delphi 6. Есть таблица, в которой хранятся пути к графическим файлам. В клиентском приложении требуется по имени файла получить картинку и вывести её пользователю. Требуется написать UDF, которой передаётся имя файла, она переписывает содержимое файла в переменную типа BLOB и возвращает её. Проблема в том, что мне никак не удаётся реализовать такую функцию.
Нашёл только функцию LoadBlobFromFile из UDFDEMO. После её выполнения что-то записывается, но точно не картинка.
Сама функция (немного изменёная):
Объявление её в базе:
Вызов:
Сама функция (немного изменёная):
Код: Выделить всё
function LoadBlobFromFile(FileName: PChar; Blob: PBlob): PBlob; cdecl; export;
const
MaxBufSize = $8192;
var
BufSize, ReadLength, StreamSize: Integer;
Buffer: PChar;
Stream: TStream;
begin
Result:=Blob;
try
Stream := TFileStream.Create(FileName, fmOpenRead or
fmShareDenyNone);
try
StreamSize := Stream.Size;
if StreamSize > MaxBufSize then BufSize := MaxBufSize
else BufSize := StreamSize;
GetMem(Buffer, BufSize);
try
while StreamSize <> 0 do begin
if StreamSize > BufSize then ReadLength := BufSize
else ReadLength := StreamSize;
Stream.ReadBuffer(Buffer^, ReadLength);
Blob^.PutSegment(Blob^.BlobHandle, Buffer, ReadLength);
Dec(StreamSize, ReadLength);
end;
finally
FreeMem(Buffer, BufSize);
end;
finally
Stream.Free;
end;
except
{$Ifdef Debug}
on E: Exception do begin
Writeln(X, 'Exception in LoadBLObFromFile!!!');
Writeln(X, 'FileName ', FileName);
Writeln(X, E.Message);
Flush(X);
end;
{$Endif}
end;
end;
Код: Выделить всё
DECLARE EXTERNAL FUNCTION GET_IMAGE
CSTRING(100),
BLOB,
BLOB
RETURNS PARAMETER 3
ENTRY_POINT 'LoadBlobFromFile' MODULE_NAME 'FreeUDFLib'
Код: Выделить всё
CREATE PROCEDURE "GetImage" (
id integer)
returns (
res integer)
as
declare variable imgid integer;
declare variable fname varchar(100);
declare variable path varchar(70);
declare variable img blob sub_type 0 segment size 16384;
BEGIN
res=0;
--получение пути к картинке
SELECT "ImageId" FROM "Object" WHERE "Id1"=:id INTO :ImgId;
select "ImageFile" FROM "Images" WHERE "Id1"=:ImgId INTO :fname;
SELECT "Value" FROM "Options" WHERE "Param"='ImagePath' INTO :path;
fname=:path||:fname;
--получение самой картинки
img=GET_IMAGE(:fname,:img);
INSERT INTO "TempObject" ("Image") VALUES (:img);
END
а если сохранить из блоба в файл - будет картинка?
кстати:
вот это безобразие в виде segment size - зачем?
кстати:
Код: Выделить всё
declare variable img blob sub_type 0 segment size 16384;
Фиг поверю, что немного. Найди отличияLeonid Kul писал(а):Нашёл только функцию LoadBlobFromFile из UDFDEMO....
Сама функция (немного изменёная):
Код: Выделить всё
function LoadBlobFromFile(FileName: PChar; Blob: PBlob): PBlob;
procedure LoadBLObFromFile(FileName: PChar; Blob: PBlob);
Не пробовал и пробовать не стану, будет ли вот так работать правильно:
Код: Выделить всё
img=GET_IMAGE(:fname,:img);
При объявлении функции, как
и следующем её вызове:
img равняется NULL (имя файла передаётся верно).
Код: Выделить всё
procedure LoadBLObFromFile(FileName: PChar; Blob: PBlob);
Код: Выделить всё
GET_IMAGE(:fname,:img);
Да понятно, понятно.
Только это совсем нетрадиционный подход.
Говорю ж - нафиг доп.параметр, который и не нужен? Функция проверено работает в том виде, как в демке. Если тебе нужна именно такая, чего эксперементируешь-то?
У меня самого такая же функция работает замечательно (и именно с картинками), и без всякой дополнительной тусовки.
(ну там ещё дополнительно прикручены функции для конвертации на лету в jpeg, но это уже так, к делу не относится).
Только это совсем нетрадиционный подход.
Говорю ж - нафиг доп.параметр, который и не нужен? Функция проверено работает в том виде, как в демке. Если тебе нужна именно такая, чего эксперементируешь-то?
У меня самого такая же функция работает замечательно (и именно с картинками), и без всякой дополнительной тусовки.
(ну там ещё дополнительно прикручены функции для конвертации на лету в jpeg, но это уже так, к делу не относится).
Вернись к родному варианту процедуры, и выполни в IBExpert'е следующее:Leonid K. писал(а):Я же написал выше, что в том виде как в демке тоже не работает. В этом случае в таблицу записывается null.
Код: Выделить всё
select GET_IMAGE ('тут путь с именем файла') from rdb$database
А то может у тебя для сервера доступа к каталогу с картинками нет, а ты тут нам про неработу UDF рассказываешь.
Всё, разобрался. Всем спасибо.
Всё, как обычно, из-за моей невнимательности. Перечитав ещё раз "Как научиться писать UDF за 21 минуту", понял свою ошибку. LoadBlobFromFile из UDFDEMO работает нормально, просто меня смутило то, что это процедура, а не функция, и я неправильно её задекларировал в Firebird.
Всё, как обычно, из-за моей невнимательности. Перечитав ещё раз "Как научиться писать UDF за 21 минуту", понял свою ошибку. LoadBlobFromFile из UDFDEMO работает нормально, просто меня смутило то, что это процедура, а не функция, и я неправильно её задекларировал в Firebird.
вот-вот. в этом плане на сайте все проверено, ошибок нет.и я неправильно её задекларировал в Firebird.
также стоило посмотреть www.ibase.ru/download/safeudf.zip
p.s. собственно, я решил сделать отдельную либу с save и load блобов.
и все вроде бы нормально, только при сохранении буфера в файл почему-то у меня лезет ошибка записи в поток. вот дела...
Интересно.kdv писал(а):только при сохранении буфера в файл почему-то у меня лезет ошибка записи в поток. вот дела...
У меня тоже была такая срань - я правда не в файл, а просто в TMemoryStream буфер пытался запихать - скрючивало.
Так и не отладил - необходимость в процедуре отпала, и руки не дошли с тех пор.
www.ibase.ru/download/blobsaveload.zip
декларация, исходник (Delphi) и dll (D2006).
Функции LoadBLOBFromFile и SaveBLOBToFile.
SaveBLOBToFile в качестве результата выдает
размер сохраненного блоба.
в blobsaveload.sql - декларация функций и пример использования.
декларация, исходник (Delphi) и dll (D2006).
Функции LoadBLOBFromFile и SaveBLOBToFile.
SaveBLOBToFile в качестве результата выдает
размер сохраненного блоба.
в blobsaveload.sql - декларация функций и пример использования.
когда Кукарцев писал на дельфях, дельфя еще позволяла над числовыми типами выполнять булевские операции.
а я не стал морочить голову, применяя wordbool.
и потом, я ж перед выкладыванием все проверил в т.ч и в отладчике. на корректность работы, отсутствие утечек памяти и т.п. ну может на ошибки всесторонне не проверял, но задача была за 5 минут слабать пару функций.
а я не стал морочить голову, применяя wordbool.
и потом, я ж перед выкладыванием все проверил в т.ч и в отладчике. на корректность работы, отсутствие утечек памяти и т.п. ну может на ошибки всесторонне не проверял, но задача была за 5 минут слабать пару функций.