Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > хранение файлов в PostgreSQL


Автор: Denis 18.8.2007, 23:29
PostgreSQL 8.2,  ADO,  Delphi7
Подскажите плиз или дайте ссылку, где можно прочесть про хранение файлов в постгре.
Какого типа должно быть поле в таблице, как производить чтение, запись.

Автор: Denis 19.8.2007, 17:53
господа, это слишком легкий и глупый вопрос или правда никто помочь не может :(
уточню вопрос нужно хранить файлы типа *.doc и *.xls. Хотелось бы, чтобы они хранились в базе а не отдельно. Подскажите тип данных в постгре для файлов.

Автор: chand0s 19.8.2007, 22:40
Цитата(Denis @ 19.8.2007,  15:53)
господа, это слишком легкий и глупый вопрос или правда никто помочь не может :(
уточню вопрос нужно хранить файлы типа *.doc и *.xls. Хотелось бы, чтобы они хранились в базе а не отдельно. Подскажите тип данных в постгре для файлов.

Я в Postgres'е вообще не рублю, но сильно подозреваю, что для хранения больших двоичных данных в этой СУБД  (как и в любой другой, в принципе), есть тип данных BLOB.

Автор: tux 20.8.2007, 00:21
Тип называется bytea. А файлы хранить рекомендуется таки отдельно.

Автор: Denis 21.8.2007, 11:53
Сделал поле в таблице типа bytea, а вот записать инфу не получается. Перерыл DRKB, пробовал несколько способов. При попытке записи *.doc пишет ошибку "Invalid class typecast"
Подскажите, как производится чтение/запись в поля (bytea) постгре-таблицы.

Автор: SergeBS 22.8.2007, 09:01
Denis
Покажи свой код.

Автор: Denis 22.8.2007, 18:06
Таблица 'temp' в постгре содержит единственное поле 'file' типа bytea
пробовал записать файл такими способами:

1) 
Код

(dm.ADOTable1.fieldbyname('file') as TBlobField).loadfromfile('c:1.doc');  

          Ошибка:"Invalid class typecast"

2)
Код

 dm.ADOquery1.sql.text:='Insert into temp (file) Values (:b)';
    dm.ADOQuery1.parameters.parseSQL(dm.ADOquery1.sql.text, true);
    dm.ADOQuery1.parameters.parambyname('b').LoadFromFile('c:\1.doc',ftBlob);
    dm.ADOQuery1.execsql;

           Ошибка:   "type "lo" does not exist"
3)
Код

var blob: TBlobStream;
begin
blob := dm.ADOTable1.CreateBlobStream(dm.ADOTable1.FieldByName('file'), bmWrite);

Автор: LSD 23.8.2007, 14:35
Это к базе данных уже не имеет отношения.

Модератор: перемещено из Общие вопросы по базам данных.

Автор: pythonwin 24.8.2007, 07:27
gрошу прощения. но думаю он пригодиться
Код
class File(SQLObject):
    data = StringCol() # 
    def _set_data(self, value):
        self._SO_set_data(value.encode('base64'))
    def _get_data(self):
        return self._SO_get_data().decode('base64')

как видно из кода, лучше хранить в TEXT - легче будет снимать дамп и поднимать его smile

Автор: Denis 24.8.2007, 12:52
pythonwin, прошу прощения за мою неграмотность, но нельзя ли немного подробнее. Честно говоря не понял как пользоваться этим кодом

Автор: pythonwin 24.8.2007, 13:24
Цитата(Denis @  24.8.2007,  15:52 Найти цитируемый пост)
pythonwin, прошу прощения за мою неграмотность, но нельзя ли немного подробнее. Честно говоря не понял как пользоваться этим кодом 

это пример на питоне
содержимое файла считывается как бинарник и перекодируется в base64 и записывается в БД

Автор: SergeBS 24.8.2007, 16:03
Denis
DRKB:
Цитата

Сохранение и чтение файлов в BLOB-полях 
Код


// Сохраняем 
procedure TForm1.Button1Click(Sender: TObject);  
var  
  blob: TBlobStream;  
begin  
  blob := yourDataset.CreateBlobStream(yourDataset.FieldByName('YOUR_BLOB'), bmWrite);  
  try  
    blob.Seek(0, soFromBeginning);  
    fs := TFileStream.Create('c:\your_name.doc', fmOpenRead or  
      fmShareDenyWrite);  
    try  
      blob.CopyFrom(fs, fs.Size)  
    finally  
      fs.Free  
    end;  
  finally  
    blob.Free  
  end;  
end; 

// Загружаем 
procedure TForm1.Button1Click(Sender: TObject);  
var  
  blob: TBlobStream;  
begin  
  blob := yourDataset.CreateBlobStream(yourDataset.FieldByName('YOUR_BLOB'), bmRead);  
  try  
    blob.Seek(0, soFromBeginning);  

    with TFileStream.Create('c:\your_name.doc', fmCreate) do  
      try  
        CopyFrom(blob, blob.Size)  
      finally  
        Free  
      end;  
  finally  
    blob.Free  
  end;  
end; 


Автор: Denis 25.8.2007, 14:12
Я первым делом перерыл DRKB (я там только один пример не пробовал) и пробовал этот пример таким образом:
Код

var
  blob: TStream;
  fs : TFileStream;
begin
  blob := dm.ADOTable1.CreateBlobStream(dm.ADOTable1.FieldByName('file'), bmWrite);
  try
    blob.Seek(0, soFromBeginning);
    fs := TFileStream.Create('c:\1.doc', fmOpenRead or
      fmShareDenyWrite);
....

если переменную описывать как  blob: TBlobStream; ругается на несооветствие типов
Пробовал так:
Код

var
  blob: TBlobStream;
  fs : TFileStream;
begin
  blob := TBlobStream.Create(dm.ADOTable1.FieldByName('file'), bmWrite);
....

пробовал вместо ADOTable использовать ADOQuery, всё без результата

Автор: SergeBS 27.8.2007, 14:56
Denis
Ну не знаю, что тебя заморочило. Вот работающий пример:
Код

{dmUsp1 - datamodule, dsDocFiles - TADODataSet -> таблица MS SQL 
CommandText = 'select * from docfiles1 where кой-какие условия для выбора именно нужного файла' 
там поле doc_value - типа Image = bytea в postgreSQL}
procedure TNamePass.GetFileFromBlob;
var
  blob1 : TStream;
begin
  with dmUsp1 do begin
    dsDocFiles1.Open;
    if dsDocFiles1.IsEmpty then
    begin
      dsDocFiles1.Close;
      MessageBox(Handle,'Не найдено обновление программы!','Проблема - записать и сообщить!',48);
      Exit;
    end;
    blob1 := dsDocFiles1.CreateBlobStream(dsDocFiles1.FieldByName('doc_value'),
      bmRead);
    try
      blob1.Seek(0, soFromBeginning);
      with TFileStream.Create(Path0 + 'komp11.exe', fmCreate) do
      try
        CopyFrom(blob1, blob1.Size);
      finally
        Free;
      end;
    finally
      blob1.Free;
      dsDocFiles1.Close;
    end;
  end;
end;

Запись - тоже по образу и подобию FAQ. Не помню - правил там типы блоба или нет. Делфи 5.

Автор: Denis 27.8.2007, 22:18
Ну а почему у меня не работает? Подскажите, плиз, где в этом коде ошибка?
Код

 {dm - datamodule, dsDocFiles1 - TADODataSet -> таблица MS SQL
CommandText = 'select * from temp'
там единственное поле file - типа bytea в postgreSQL}
var
  blob : TStream;
  fs : TFileStream;
begin
    blob := dm.dsDocFiles1.CreateBlobStream(dm.dsDocFiles1.FieldByName('file'), bmWrite);
  try
    blob.Seek(0, soFromBeginning);
    fs := TFileStream.Create('c:\1.doc', fmOpenRead or fmShareDenyWrite);
    try
      blob.CopyFrom(fs, fs.Size)
    finally
      fs.Free
    end;
  finally
    blob.Free
  end;

Автор: SergeBS 28.8.2007, 07:26
Denis
Цитата
blob := dm.dsDocFiles1.CreateBlobStream(dm.dsDocFiles1.FieldByName('file'), bmWrite);

У тебя.
Цитата
blob1 := dsDocFiles1.CreateBlobStream(dsDocFiles1.FieldByName('doc_value'),
      bmRead);

У меня. Разницу не видишь?

Автор: Denis 28.8.2007, 08:12
Я там уже и bmRead, и bmWrite, и bmReadWrite там пробовал ставить. Всегда одна и та же Ошибка:"Invalid class typecast"

Автор: SergeBS 28.8.2007, 16:00
Denis
А остальные строчки кто смотреть будет? Смешал коды записи в блоб-поле и чтения из блоба в четр-те что. ВНИМАТЕЛЬНО смотри на код чтения из блоба. И смотри в какой строке.

Автор: Denis 28.8.2007, 17:18
SergeBS, до остальных строчек программа не доходит smile
на самой первой строке
blob := dm.dsDocFiles1.CreateBlobStream(dm.dsDocFiles1.FieldByName('file'), bmRead);
выдает ошибку :(
Может с таблицей что не так?
Код

CREATE TABLE "temp"
(
  file bytea

WITHOUT OIDS; 
ALTER TABLE "temp" OWNER TO postgres;


Добавлено через 1 минуту
SergeBS, до остальных строчек программа не доходит smile
на самой первой строке
blob := dm.dsDocFiles1.CreateBlobStream(dm.dsDocFiles1.FieldByName('file'), bmRead);
выдает ошибку :(
Может с таблицей что не так?
Код

CREATE TABLE "temp"
(
  file bytea

WITHOUT OIDS; 
ALTER TABLE "temp" OWNER TO postgres;


Добавлено через 9 минут и 44 секунды
SergeBS, до остальных строчек программа не доходит smile
на самой первой строке
blob := dm.dsDocFiles1.CreateBlobStream(dm.dsDocFiles1.FieldByName('file'), bmRead);
выдает ошибку :(
Может с таблицей что не так?
Код

CREATE TABLE "temp"
(
  file bytea

WITHOUT OIDS; 
ALTER TABLE "temp" OWNER TO postgres;


Автор: SergeBS 29.8.2007, 07:42
Denis
А теперь переименуй название поля file в file1 хотя бы - использовать ключевые слова как названия полей - иметь лишние грабли. У делфи вполне может от этого башню снести.
Кроме создания таблицы нужно бы ее и заполнить.

Автор: Denis 29.8.2007, 07:59
SergeBS, с названием поля све нормально, пробовал и другие. А таблицу надо из Delphi заполнить. Или ее до использования надо заполнить чем то? Если да, то как в постгре заполнить поле типа bytea?

Автор: SergeBS 29.8.2007, 09:22
Denis
Ну так заполняй таблицу как описано в DRKB. Единственное - объявления типов в var - тоже нужно подобрать. Заполни таблицу, и имя все-таки поставь не конфликтующее с зарезервированными словами.

Автор: Denis 29.8.2007, 15:15
Но как можно заполнить базу, если при создании потока возникает ошибка? Переменная типа TBlobStream не подходит. Ведь если у тебя пример работает, а у меня такой же код нет, то я что-то делаю не так, но вот никак не могу найти ЧТО?

Автор: SergeBS 30.8.2007, 08:37
Denis,
Еще раз:
Цитата
Ну так заполняй таблицу как описано в DRKB. Единственное - объявления типов в var - тоже нужно подобрать.

Читать умеешь?
Код

procedure TMain.SaveFileToBlob;
var
  blob1 : TStream;
  fs : TFileStream;
...


Автор: Denis 30.8.2007, 08:57
Цитата

Ну а почему у меня не работает? Подскажите, плиз, где в этом коде ошибка?код Pascal/Delphi
Код

{dm - datamodule, dsDocFiles1 - TADODataSet -> таблица MS SQL
CommandText = 'select * from temp'
там единственное поле file - типа bytea в postgreSQL}
var
  blob : TStream;
  fs : TFileStream;
begin
....


Я ж так и писал! Но это не работает! Я уже не знаю какие типы еще пробовать!

Автор: SergeBS 30.8.2007, 09:34
Denis,
Проверяй, есть ли вообще таблица, сколько в ней записей и т.п. 
Цитата

Я ж так и писал! Но это не работает! Я уже не знаю какие типы еще пробовать! 
 
Значит по неопытности грабли себе построил еще где-то. Например на Делфи обновления не ставил. Версия Делфи? Версия ADO?

Автор: Denis 30.8.2007, 20:55
SergeBS
Delphi7, таблица не содержит ни одной записи, т.к. заполнить не могу smile Надеюсь что получится когда-нить. А потом еще столь ко же с чтением буду мчаться smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)