Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / хранение файлов & постгрис / 14 сообщений из 14, страница 1 из 1
02.10.2006, 20:50
    #34027162
Кифирчик
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
Уважаемые гуру, возможно ли на постгрисе реализовать такое:
1) файлы хранятся на одном компьютере с запущеном сервере БД
2) в базе данных есть ссылки на эти файлы
3) когда удалённый пользователь запрашивает файл, то постгрис читает его с диска и передаёт выражении SELECT
4) когда удалённые пользователь хочет сохранить(заменить)файл, постгрис получает его как параметр к запросу INSERT (UPDATE), и сохраняет не БД а на жесткий диск в опредённый каталог
5) удалённый пользователь не имеет доступа к файлам на диске
6) по возможности чтобы при чтении/сохранении/обновлении файла, постгрис жал его каким-нить архиватором

?
...
Рейтинг: 0 / 0
03.10.2006, 00:36
    #34027354
Кувалдин Роман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
Разве что создать свой тип и работать с ним через Си-шные хранимые процедуры...


=====================================
Страну, в которой все ходят на бровях,
на колени не поставишь...
=====================================
...
Рейтинг: 0 / 0
03.10.2006, 06:52
    #34027455
Serik Akhmetov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
у меня была задача только по чтению файлов с диска, написал сам процедуры

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
-- Function: file_get_size(text)

-- DROP FUNCTION file_get_size(text);
CREATE OR REPLACE FUNCTION file_get_size(text)
  RETURNS int4 AS
$BODY$
my $file=@_[ 0 ];
my $f,$ret;

$ret = '';

open($f,"<".$file);
if ($f)
{
 binmode($f);
 seek ($f, 0 , 2 );
 $ret = tell($f);
 close($f);
}
else
{ 
 $ret = - 1 ;
}
                                        
 return($ret);               
$BODY$
  LANGUAGE 'plperlu' VOLATILE;
ALTER FUNCTION file_get_size(text) OWNER TO postgres;


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
-- Function: file_read2(text, int4, int4)

-- DROP FUNCTION file_read2(text, int4, int4);
CREATE OR REPLACE FUNCTION file_read2(text, int4, int4)
  RETURNS bytea AS
$BODY$
my $file      = @_[ 0 ];    # Имя файла
my $start_pos = @_[ 1 ];    # Смещение от начала
my $length    = @_[ 2 ];    # Прочесть кол-во байт

my $f,$s,$v,$ret;
my $c;

$ret = '';
#$c   =  0 ;

open($f,"<".$file);
seek($f,$start_pos, 1 );
binmode($f);
while($length >  0 )
{
 read($f,$s, 1 );
 $v = unpack("C",$s);
 if ( ($v>= 0  && $v<= 31 ) || ($v>= 127  && $v<= 255 ) || ($v== 39 ) || ($v== 92 ))
 {
  my $substr;
  $substr = sprintf("%03o",$v);
  $ret .= "\\".$substr;
 }
 else
 {
  $ret .= $s;
 }
 $length--;
} # while


close($f);
                                        
return ($ret); 

$BODY$
  LANGUAGE 'plperlu' VOLATILE;
ALTER FUNCTION file_read2(text, int4, int4) OWNER TO postgres;

сделай аналогично для записи.
...
Рейтинг: 0 / 0
03.10.2006, 13:55
    #34028678
Andrew Sagulin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
А так не проще?
Код: plaintext
1.
2.
3.
4.
5.
6.
CREATE OR REPLACE FUNCTION file_get_size(text)
  RETURNS int4 AS
$BODY$
my $file = @_[ 0 ];
return (-e $file) ? (-s $file) : - 1 ;
$BODY$
LANGUAGE 'plperlu' VOLATILE;

Но это так, к слову. :)
...
Рейтинг: 0 / 0
03.10.2006, 19:25
    #34029907
J.W.
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
А если уж нужно совсем просто, тогда так - встроенные ф-ии работы с файлами, есть в 8.1:
Код: plaintext
1.
pg_read_file(filename text, offset bigint, length bigint)
pg_stat_file(filename text)
...
Рейтинг: 0 / 0
04.10.2006, 07:26
    #34030363
Serik Akhmetov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
J.W.А если уж нужно совсем просто, тогда так - встроенные ф-ии работы с файлами, есть в 8.1:
Код: plaintext
1.
pg_read_file(filename text, offset bigint, length bigint)
pg_stat_file(filename text)


текстовые файлы в домашней папке PostgreSQL
...
Рейтинг: 0 / 0
07.10.2006, 22:51
    #34039856
Кифирчик
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
ага
как я понял будь это самописная функция на перле, или на C++, или встроенная pg_read... вылезти за пределы домашнего каталога и тем более на другой компьютер не получится, так? или есть варианты? может можно посылать сигналы/сообщения своему процессу, который передаст файл во временный, доступный постгрису каталог?

сложность в том, что если давать ссылку например в расшареном по NetBios или HTTP ресурсе, то выходит должны быть доступны доступны все файлы
а надо разграничивать доступ надо иметь возможность изменять файлы
...
Рейтинг: 0 / 0
09.10.2006, 03:37
    #34040514
фффф
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
Кифирчикага
как я понял будь это самописная функция на перле, или на C++, или встроенная pg_read... вылезти за пределы домашнего каталога и тем более на другой компьютер не получится, так? или есть варианты? может можно посылать сигналы/сообщения своему процессу, который передаст файл во временный, доступный постгрису каталог?

сложность в том, что если давать ссылку например в расшареном по NetBios или HTTP ресурсе, то выходит должны быть доступны доступны все файлы
а надо разграничивать доступ надо иметь возможность изменять файлы
Для самописной функции никаких ограничений относительно каталога нет. Куда есть доступ юзеру, под которым запущен серверный процесс - туда и можно ходить.
...
Рейтинг: 0 / 0
09.10.2006, 09:13
    #34040643
Serik Akhmetov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
КифирчикУважаемые гуру, возможно ли на постгрисе реализовать такое:
1) файлы хранятся на одном компьютере с запущеном сервере БД
2) в базе данных есть ссылки на эти файлы
3) когда удалённый пользователь запрашивает файл, то постгрис читает его с диска и передаёт выражении SELECT
4) когда удалённые пользователь хочет сохранить(заменить)файл, постгрис получает его как параметр к запросу INSERT (UPDATE), и сохраняет не БД а на жесткий диск в опредённый каталог
5) удалённый пользователь не имеет доступа к файлам на диске
6) по возможности чтобы при чтении/сохранении/обновлении файла, постгрис жал его каким-нить архиватором
?

Есть клиентская программа, и есть сервер.
Клиент посылает данные, а сервер их хранит.
Моя функция выдает уже сохраненные на диске сервера файлы.
Напиши свою функцию, в которую будет передавать данные клиент, а сервер их будет записывать на свой диск. При этом откуда будет браться исходный файл, это забота клиента.
А делать из сервера БД прокси для чтения/записи файлов хоть откуда, IMHO не очень правильно, хотя вполне реально. При этом не забывай, что bytea передается кодированный, что для бинарных файлов многократно увеличивает объем данных (соответственно трафик и нагрузка на сервер).

т.е. для 1,2,3 подходит моя функция,
для 4 нужно написать соответсвующую функцию,
для 6 у меня есть еще одна функция, выполняет команду на сервере

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
-- Function: command(text)

-- DROP FUNCTION command(text);
CREATE OR REPLACE FUNCTION command(text)
  RETURNS SETOF text AS
$BODY$
my $command = $_[ 0 ];
my @ret;
my $res =[];
 @ret = `$command`;
 for(my $i= 0 ;$i<=$#ret;$i++)
    {
     $ret[$i] = substr($ret[$i], 0 ,- 1 ); # убираем символ переноса строки
     push @$res, $ret[$i];
    }
return $res;
$BODY$
  LANGUAGE 'plperlu' VOLATILE;
ALTER FUNCTION command(text) OWNER TO postgres;
COMMENT ON FUNCTION command(text) IS 'выполнение комманды ОС и возврат результата';

т.е. функцией 4 записываешь файл во временную папку на сервере,
потом

Код: plaintext
1.
2.
select * from 
command ('bzip /tmp/newfile; mv /tmp/newfile.bz2 /var/path/to/repos/...';);

для получения файла выполняешь на сервере

Код: plaintext
1.
2.
select * from 
command ('cp /var/path/to/repos/... /tmp/newfile.bz2 '; bzip -d /tmp/newfile.bz2;);

и на клиенте его читаешь

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
//---------------------------------------------------------------------------
void TfrmReadFile::read(void)
{
 AnsiString sql;
 PGresult * res;
 FILE * f;
 long fsize, x1,x2,step;
 char tmppath[ 1024 ]; AnsiString fullname;

 // Получение размера файла

 sql = "select file_get_size($$";
 sql +=filename;
 sql +="$$)::int4;";

 res = pg.exec(sql);

 if (pg.PQresultStatus(res) != PGRES_TUPLES_OK)
  {
   ShowMessage("Ошибка чтения данных.");
   pg.PQclear(res);
   ret = - 1 ;
   return;
  }
 else
  {
   fsize = StrToInt(pg.PQgetvalue(res, 0 , 0 ));
   pg.PQclear(res);
  }

 if (fsize == - 1 )
 {
  ShowMessage("Ошибка получения размера файла.");
  ret = - 1 ;
  return;
 }

 // Путь во временной папке
 if (GetTempPath(sizeof(tmppath),tmppath)> 0 )
 {
   fullname = AnsiString(tmppath) +"out.mp3";
 }
 else
  {
   ShowMessage("Ошибка получения пути к папке временных файлов. Обратитесь с системному администратору.");
   ret = - 1 ;
   return;
 }

// f     = fopen("c:\\temp\\out.mp3","wb");
 f     = fopen(fullname.c_str(),"wb");
 if (f==NULL)
   {
    ShowMessage("Ошибка открытия файла " + fullname);
    ret = - 1 ;
    return;
   }

  // Чтение данных
 step =  102400 ;
 for(x1= 0 ;x1<fsize;x1+=step)
 {
  if ((x1+step) < fsize) x2=step;
  else x2 = fsize - x1;

  sql = "select file_read2($$";
  sql +=filename + "$$," + IntToStr(x1) +"," + IntToStr(x2) +")::bytea;";
  res = pg.exec(sql);

  if (pg.PQresultStatus(res) != PGRES_TUPLES_OK)
   {
    ShowMessage("Ошибка чтения данных.");
    pg.PQclear(res);
    fclose(f);
    ret = - 1 ;
    return;
   }
 else
  {
    size_t bytealen, wr;

    char *encstr;
    encstr = pg.PQunescapeBytea(pg.PQgetvalue(res, 0 , 0 ),&bytealen);
    wr = fwrite(encstr,bytealen, 1 ,f);
    if (wr != bytealen) {/*ShowMessage("Ошибка записи файла !");*/}

    pg.PQfreemem(encstr);
    pg.PQclear(res);
  }
 // Индикатор
  pbReadFile -> Position = ((x1+x2)* 100 )/fsize;
  lstr->Caption = IntToStr(x1+x2) + "/" + IntToStr(fsize) + " : " + IntToStr(((x1+x2)* 100 )/fsize) + "%";
  Refresh();
  Sleep( 1 );
 } // for
 fclose(f);

 ret =  1 ;
}
//---------------------------------------------------------------------------
...
Рейтинг: 0 / 0
09.10.2006, 09:16
    #34040652
Serik Akhmetov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
готов обсудить размер гонорара за разработку функции 4
...
Рейтинг: 0 / 0
09.10.2006, 18:05
    #34042591
Кифирчик
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
to Serik Akhmetov
Огромное спасибо за инфу, для меня это действительно то, что надо,
На счёт "гонорара" - я к сожалению не работодатель, и этот проект для меня представляет больше академический интерес чем комерческий, к тому же все части этой головломки есть, осталось врубиться в особенности технической реализации.
...
Рейтинг: 0 / 0
10.10.2006, 07:00
    #34043134
Serik Akhmetov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
Подозреваю, что следующий вопрос будет "Как представить эти данные",
см. http://fuse.sourceforge.net/
...
Рейтинг: 0 / 0
10.10.2006, 21:28
    #34045685
Кифирчик
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
:)
"Как представить эти данные"?
клиенты под форточками
если я смог прочитать постгрисом файл, то затем передаём его клиенту, тот в свою очередь сохраняет во временную папку и файл открывается соответствующим приложением, это строк 10...15 кода
какие сложности в предствалении этих данных?
Тут блин проблемма, что перл не ставится, и сишные библиотеки:
ERROR: could not find function "add_one" in file "D:/Program Files/PostgreSQL/8.1/lib/add_one.dll" хотя всё там есть :(

Сервак в ближайшем будущем передет на линуху, и рассматривается ещё и такой вариант:
- на серваке, для каждого пользователя программы, создаётся NetBios (ftp, http) папка, пароль получает клиент из БД
- когда пользователь запрашивает файл, то СУБД, системными командами переносит(распаковывает) его в индивидуальную для пользователя папку, и передаёт клиенту ссылку
- когда пользователь хочет внести новый/сохранить изменённый файл, то клиент закачивает его в папку пользователя на сервере и передаёт ссылку на него постгрису, а тот жмёт его и кидает в спец каталог
Что думаете по этому поводу? вроде и сервак не напрягаем пережевыванием файлов, и разграничиваем права на информацию
мне кажется единственная сложность может быть в определении "как долго держать распакованный файл в папке пользователя"
...
Рейтинг: 0 / 0
11.10.2006, 07:17
    #34045939
Serik Akhmetov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
хранение файлов & постгрис
КифирчикТут блин проблемма, что перл не ставитсяПод Windows устанавливаешь ActivePerl и делаешь createlang

Кифирчик"как долго держать распакованный файл в папке пользователя"Пользователь работает напрямую с файлом на сервере ? или все таки клиенская программа скачивает файл во временную папку ? В любом случае ответ дает клиенская программа, в крайнем случае просто при входе в программу чистить свою папку на сервере.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / хранение файлов & постгрис / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]