Загрузка рисунков в БД

В процессе работы, достаточно часто возникает ситуация, когда работать приходится не только со стандартными типами данных в базе, но и с изображениями, звуками и другими неструктурированными объектами. При этом можно выделить два основных подхода к хранению подобной информации: 1. В БД хранится только путь к файлу, сам файл хранится на жестком диске. 2. Весь объект хранится в БД в сециальном поле с типом blob
В ряде серверов БД, например Micro$oft SQL 2008 появилась возможность объединить эти подходы, отчасти устранив ряд недостатков первого и второго. Но как обычно у гибридов, решив несколько старых проблем, приобретаем несколько новых. Впрочем речь не об этом.
В этой статье я хотел бы еще раз рассмотреть тему сохранения и извлечения неструктурированной информации на примере сервера БД Firebird и Borland Builder C++ 6. Что бы не усложнять материал, я буду рассматривать работу с рисунками (точнее фотографиями) в формате bmp и jpeg. И затем расскажу как можно расширить приведенную схему.
Итак для работы на нужно создать таблицу, которая содержит идентификатор и связанное с ним изображение. Делает это следующий скрипт:
CREATE TABLE PEOPLE_PHOTOS (
PEOPLE_ID INTEGER NOT NULL,
PEOPLE_PHOTO BLOB SUB_TYPE 0 SEGMENT SIZE 80 NOT NULL
);
Для операции вставки (модификации) служит хранимая процедура:
CREATE OR ALTER PROCEDURE PEOPLE_PHOTO_INS (
people_id integer,
people_photo blob sub_type 0 segment size 80)
as
declare variable tmp_count integer = 0;
begin
/* Procedure Text */
select count(*) from people_photos where people_id = :people_id into :tmp_count;
if (:tmp_count = 1) then
begin
update people_photos set
people_photo = :people_photo where people_id = :people_id;
end
else if (:tmp_count = 0) then
begin
insert into people_photos (people_id, people_photo) values (:people_id, :people_photo);
end
suspend;
end
Для выборки
CREATE OR ALTER PROCEDURE PEOPLE_PHOTO_SEL (
people_id integer)
returns (
people_photo blob sub_type 0 segment size 80)
as
begin
/* Procedure Text */
select people_photo from people_photos where people_id = :people_id into :people_photo;
suspend;
end
Добавлению изображения в базу на стороне клиента служит следующий код:
//Заносим в параметр идентификатор
dmMain->fibPhotoIns->ParamByName("people_id")->Value = PeopleId;
TMemoryStream *pMS = new TMemoryStream;
Graphics::TBitmap *tmpBitmap = new Graphics::TBitmap;
TJPEGImage *tmpImg = new TJPEGImage();
try{
//Загружаем изображение из файла и сохраняем его в поток
//если это JPEG
tmpImg->LoadFromFile(opOpen->FileName);
tmpImg->SaveToStream(pMS);
}catch(...){
//если нет - то обрабатываем исключение и загружаем битмеп
tmpBitmap->LoadFromFile(opOpen->FileName);
tmpBitmap->SaveToStream(pMS);
}
//Загружаем из потока в параметр и вызываем процедуру
dmMain->fibPhotoIns->ParamByName("people_photo")->LoadFromStream(pMS);
dmMain->fibPhotoIns->ExecProc();
delete pMS;
delete tmpBitmap;
delete tmpImg;
Соотвественно получение изображения из базы в компонент TImage
imPhoto->Picture->Bitmap->CleanupInstance();
dmMain->fibPhoto->ParamByName("people_id")->Value = tmp;
dmMain->fibPhoto->Active = true;
TMemoryStream *pMS = (TMemoryStream*)dmMain->fibPhoto->CreateBlobStream(dmMain->fibPhoto->FieldByName("people_photo"),bmRead);
if(!pMS->Size){
dmMain->fibPhoto->Active = false;
return;
}
TJPEGImage *tmpImage = new TJPEGImage();
Graphics::TBitmap *tmpBitmap = new Graphics::TBitmap;
try{
pMS->Position = 0;
tmpImage->LoadFromStream(pMS);
imPhoto->Picture->Bitmap->Assign(tmpImage);
}
catch(...){
pMS->Position = 0;
tmpBitmap->LoadFromStream(pMS);
imPhoto->Picture->Bitmap->Assign(tmpBitmap);
}
delete pMS;
delete tmpImage;
delete tmpBitmap;
dmMain->fibPhoto->Active = false;
Обращаю ваше внимание - не забывайте устанавливать позицию потока в 0. Если вы получаете ошибку "JPEG error #52" - значит либо вы забыли это сделать, либо ваш файл не JPEG.
Если в работе вам надо использовать более чем два типа файлов, то генерация исключений будет достаточно накладным решением. В таком случае нужно дополнительно вводить поле типа файла и обрабатывать его, оставляя исключения только для ошибок, либо же пытаться распознавать тип файла по сигнатуре.
Обсудить статью на форуме
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии


Комментарии
Re: Загрузка рисунков в БД
БД - база данных.
============================================
Во имя Отца и Сына и Святаго Духа
Re: Загрузка рисунков в БД
А что такое БД?
И с чем его едят?