Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Последние темы форума

Показать новые сообщения »

Почтовая рассылка

Подписчиков: 11631
Последний выпуск: 19.06.2015

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

Автор: Константин Малахов
31 марта 2009 года

В процессе работы, достаточно часто возникает ситуация, когда работать приходится не только со стандартными типами данных в базе, но и с изображениями, звуками и другими неструктурированными объектами. При этом можно выделить два основных подхода к хранению подобной информации: 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.

Если в работе вам надо использовать более чем два типа файлов, то генерация исключений будет достаточно накладным решением. В таком случае нужно дополнительно вводить поле типа файла и обрабатывать его, оставляя исключения только для ошибок, либо же пытаться распознавать тип файла по сигнатуре.

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
5.0K
31 декабря 2006 года
Fubu_By
74 / / 31.12.2006
+1 / -1
Мне нравитсяМне не нравится
21 апреля 2009, 14:42:02
зачем в базе хранить зображения и т.п. это ведь большая нагрузка и замедляет работу БД...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог