rtyug

rtyug
Рейтинг
263
Регистрация
13.05.2009
Должность
perl,php,sql,javascript(jquery),freebsd/linux
Интересы
perl,php,sql,javascript(jquery),freebsd/linux
https://minfin.com.ua/blogs/94589307/115366/

ну и правильно, только зря спрашивали :)

frantic, а что мешает протестировать?

все уже есть, даже ничего изобретать не надо... но через FastCGI/CGI/Mod_php будет плохо (или очень плохо)...

кстате, а в каком режиме php? елси FastCGI может ситуация не много лучше будет...

pg-lo-read-all (или свою написать) pg-lo-create

пример из php.net:


<?php
// --------- OPEN CONN ---

$conn = pg_connect("host='127.0.0.1' dbname='test' user='usertest' password='passtest'");

// --------- OPEN FILE ---

$fp = fopen('logo.gif', "r");
$buffer = fread($fp, filesize('logo.gif'));
fclose($fp);

// --------- CREATE - INSERT OID ---

pg_exec($conn, "begin");

$oid = pg_locreate($conn);

$rs = pg_exec($conn,"INSERT INTO test(tipo, images) VALUES('A1', $oid);");
$handle = pg_loopen ($conn, $oid, "w");

pg_lowrite ($handle, $buffer);
pg_loclose ($handle);

pg_exec($conn, "commit");

// --------- OPEN - INSERT OID ---

$rs = pg_exec($conn, "SELECT images FROM test WHERE tipo = 'A1';");
$row = pg_fetch_row($rs, 0);

pg_exec($conn, "begin");
$loid = pg_loopen($conn, $row[0], "r");

header("Content-type: image/gif");

pg_loreadall($loid);
pg_loclose($loid);

pg_exec ($conn, "commit");

// --------- UNLINK OID ---

pg_exec($conn, "begin");

$loid = $row[0];
pg_lounlink($conn, $loid);

pg_exec ($conn, "commit");

// --------- DELETE OID ---

pg_exec($conn, "DELETE FROM test WHERE tipo = 'A1';");

// --------- CLOSE CONN ---

pg_close();
?>

frantic, в PostgreSQL есть API для seek, чтобы бинарный файлик по байтово отдавать, но как вы будите его отдавать на веб?

или толкать прямо на страницу, или через врапер? :)

lo_lseek

$loc = $dbh->pg_lo_lseek($lobj_fd, $offset, $whence);

Changes the current read or write location on the large object $obj_id. Currently $whence can only be 0 (which is L_SET). Returns the current location and undef upon failure. This function cannot be used if AutoCommit is enabled.

т.е. лучше файлы или MogileFS

тут вот http://dbmail.org/ почтовый сервер на СУБД, там где-то рекомендовали исключительно PostgreSQL для храннения файлов (писем), если база большая, и там используються транзакции с InnoDB (по этому с файлами жестко), но и на веб-страницу там никто не отдает...

frantic, на счет стримминга, то для видео и т.д. я пример привел

nginx - картинки отдаст быстрее, лучше чем отдавать с базы....

если с базы, то может будет не много и на веб-сервер паразитная некая нагрузка...

и если картинки в базе будут более 100-150kб, а 1М примерно, то для СУБД тоже будет не красиво...

я видел некоторые хранят превиюшки по 5-30кб в MySQL (как обычный текст)

не знаю, почему, я бы все таки сделал в файлах... :)

на сколько я знаю, то максимальное ограничение файлов (и каталогов) в одном каталоге за которой ОС будет притормажить составляет около 2 млн файлов (точно не помню)... (а в вашем лучае только 60 тыщ)

можно взять сервер, и поставить распределенную файловую систему... MogileFS (http://www.google.com.ua/#hl=uk&q=mogilefs+freebsd&meta=&aq=0&aqi=g1&aql=&oq=MogileFS+f&gs_rfai=&fp=a1e4a221592c4a20)

в Oracle и MsSQL можно даже видео клипы смотреть из базы :D

есть втроенные типы STREAM

в MySQL почему-то не включили такой тип, хотя в PgSQL вроде бы есть минимальная возможонсть такая с функцией seek из BLOB

(но я не пробовал)

Example: Streaming character data from the database

In this example, we demonstrate a technique for streaming data from the database to a file handle, in this case STDOUT. This allows more data to be read in and written out than could be stored in memory at a given time.

my $lob_id = 17; # Arbitrary row identifier, for example

$sth = $dbh->prepare( <<" SQL", { ora_auto_lob => 0 } );
SELECT chardata
FROM lob_example
WHERE lob_id = ?
SQL
$sth->execute( $lob_id );
my ( $char_locator ) = $sth->fetchrow_array();

my $chunk_size = 1034; # Arbitrary chunk size, for example
my $offset = 1; # Offsets start at 1, not 0
while(1) {
my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size );
last unless length $data;
print STDOUT $data;
$offset += $chunk_size;
}

Notice that the select statement does not contain the phrase "FOR UPDATE". Because we are only reading from the LOB Locator returned, and not modifying the LOB it refers to, the select statement does not require the "FOR UPDATE" clause.

A word of catution when using the data retruned from an ora_lob_read in a condtional statement. for example if the code below;

while( my $data = $dbh->ora_lob_read( $char_locator, $offset, $chunk_size ) ) {
print STDOUT $data;
$offset += $chunk_size;
}

was used with a chunk size of 4096 against a blob that requires more than 1 chunk to return the data and the last chunk is one byte long and contains a zero (ASCII 48) you will miss this last byte as $data will contain 0 which PERL will see as false and not print it out.

http://search.cpan.org/~pythian/DBD-Oracle-1.23/Oracle.pm#Example:_Streaming_character_data_from_the_database

dima yurgensen, видно как вы хотите решить свою проблему...

закажите лучше уже чтобы кто-то сделал, например bearman

в Белоруссии полностью запретили :)

пример на Украине - только идиоты могли придумать такие законы...

view'er, имхо, таких алгоритмов больше чем предостаточно в гугле, я уже не помню какой я использовал, они все одинаковые, только что нашел:

(можете изменить их как хотите...)


<?php
function table($nameArray){
GLOBAL $_POST, $_GET;
if (isset($_POST['page'])) {
$page = intval($_POST['page']);
} else if (isset($_GET['page'])) {
$page = intval($_GET['page']);
} else {
$page = 1;
}
if ($page == 0) {
$page = 1;
}
$st = 3; // количество столбцов
$maxRecords = 3; // Количество записей на страницу
$allRecords = sizeof($nameArray);
$maxPages = floor(($allRecords / $maxRecords) / $st); // Добавляем $st, т.к. вывод идёт еще и колоночно, а если обычно, то не нужно
if ($page == 1) {
$start = 0;
$finish = $maxRecords;
} else {
$start = ($page * $maxRecords) - $maxRecords;
$finish = $page * $maxRecords;
}
//echo $page."<br>";
//echo $allRecords."<br>";
//echo $start."<br>";
//echo $finish."<br>";
$a = "<table border=0 width= '100%' align='center'>";
for($i = $start; $i < $finish; $i++){
$a .= "<tr>";
for($j = 0;$j < $st; $j++){
$a .= (isset( $nameArray[(($i*$st)+$j)]))? "<td>".$nameArray[(($i * $st)+$j)]."</td>": '';
}
$a .= "</tr>";
}
$a .= "</table>";
echo $a;
echo "<center>";
if (($allRecords % $maxRecords) != 0) {
$maxPages++;
}
if ($page != 1) {
echo " <a href=\"".$_SERVER['PHP_SELF']."?page=1\">&lt;&lt;</a> ";
}
if ($page == 1) {
echo " &lt;&lt; ";
}
if ($page >= 3) {
echo " <a href=\"".$_SERVER['PHP_SELF']."?page=".($page - 2)."\">".($page - 2)."</a> ";
}
if ($page != 1) {
echo " <a href=\"".$_SERVER['PHP_SELF']."?page=".($page - 1)."\">".($page - 1)."</a> ";
}
echo " ".$page." ";
if ($page < $maxPages) {
echo " <a href=\"".$_SERVER['PHP_SELF']."?page=".($page + 1)."\">".($page + 1)."</a> ";
}
if (($page + 1) < $maxPages) {
echo " <a href=\"".$_SERVER['PHP_SELF']."?page=".($page + 2)."\">".($page + 2)."</a> ";
}
if ($page != $maxPages) {
echo " <a href=\"".$_SERVER['PHP_SELF']."?page=".$maxPages."\">&gt;&gt;</a> ";
}
if ($page == $maxPages) {
echo " &gt;&gt; ";
}
echo "</center>";
}
?>

вот который сейчас:


sub build_pages {
my $self = shift;
my ( $url, $count, $cuttent_page, $url_panel, $max_page, $class_id ) = @_;

my ( $count_limit, $page );

$max_page ||= '10';

# $count ||= 0;

$cuttent_page = 0 if ($count == 0);

$cuttent_page = $cuttent_page || '';

my $total_pages = ceil( $count / $max_page );

$count_limit = 0;

if ( ( $cuttent_page eq 'end' && $total_pages > 0 )
|| ( $cuttent_page =~ /^\d+$/ && $cuttent_page > $total_pages ) )
{
# print '11 '.$total_pages ;
$cuttent_page = $total_pages;

}

if ( $cuttent_page =~ /^\d+$/ ) {
$count_limit = ( $cuttent_page - 1 ) * $max_page;
}

$cuttent_page = 1 if ( $cuttent_page !~ /^\d+$/ );

$class_id = $class_id ? "class='".$class_id."'" : '';



my $page_number;
my $i;
for ( $i = 0 ; $i < $total_pages ; $i++ ) {

$page_number++;
last if ( $total_pages <= 1 );

next if ( $page_number > $cuttent_page + 4 );
next if ( $page_number < $cuttent_page - 4 );

if ( $page_number > $cuttent_page + 3 ) {

$page .=
' <a '.$class_id.' href="'
. $url . ''
. $total_pages . ''
. ( $url_panel || '' )
. '"> | ... '
. $total_pages
. ' | </a>';

next;
}

if ( $page_number < $cuttent_page - 3 ) {

$page .=
' <a '.$class_id.' href="'
. $url . ''
. $page_number . ''
. ( $url_panel || '' )
. '"> | 1... | </a>';

next;
}

if ( $page_number != $cuttent_page ) {

$page .=
' <a '.$class_id.' href="'
. $url . ''
. $page_number . ''
. ( $url_panel || '' ) . '"> | '
. $page_number
. ' | </a>';
}
else {

$page .=
' <a '.$class_id.' href="'
. $url . ''
. $page_number . ''
. ( $url_panel || '' )
. '"> | <b>'
. $page_number
. '</b> |</a>';

}
}

return ( $count_limit, $page, $max_page );

}


my ( $count_limit, $page, $max_page ) = $c->model('DBI')->build_pages( $url, $count, $id_page, $max_line || undef);
# $max_line - default 10

====

еще другой:


#!perl
use HTML::Template;
use CGI qw(:standard);
# имитация загрузки данных из базы
my %data = map { $_, {id => $_, data => time ^ $_} } 0 .. 42;
my $total_data = scalar keys %data;
# позволим пользователю выбирать кол-во записей на страницу (можно в куки засунуть)
my $default_per_page = 20;
my $per_page = int url_param('per_page') || $default_per_page;
my $offset = int url_param('offset') || 0;
# вывести последнюю страницу, на случай, если у кого ручки шаловливые окажутся)
$per_page = $default_per_page if $per_page > $total_data;
$offset = $total_data - $per_page if $offset > $total_data;
# сюда будут выбраны записи для отображения (от текущего смещения до текущеего смещения + кол-во записей на страницу)
my $tmpl_data = [];
for($offset .. $offset + $per_page) {
last unless defined $data{$_}; # на случай, если записей осталось меньше, чем выводится на страницу
push @$tmpl_data, delete $data{$_}
}
# признак наличия следующей страницы: текущее смещение + кол-во записей на страницу должно быть меньше общего кол-ва записей
my $has_next = ($offset + $per_page) < $total_data;
my $next_page = $has_next ? $offset + $per_page : '';
# признак наличия предыдущей страницы: смещение больше нуля (т.е. мы не в начале)
my $has_prev = $offset > 0;
my $prev_page = $has_prev ? $offset - $per_page : '';
# запишем сюда все страницы для того, чтобы можно было перескакивать на любую страницу
# page - номер страницы (+1 для того, чтобы нумерация не начиналась с нуля)
# offset = кол-во записей на страницу * на номер текущей страницы
# per_page надо указывать для того, чтобы сохранялось нестандартное значение
my $all_pages = [ map +{page => $_+1, offset => $per_page*$_, per_page => $per_page},
0 .. int($total_data / $per_page) # кол-во страниц = общее число записей / кол-во записей на страницу
];
my $tmpl = HTML::Template->new(filename => 'pager.html');
$tmpl->param(
tmpl_data => $tmpl_data,
all_pages => $all_pages,
has_next => $has_next,
next_page => $next_page,
has_prev => $has_prev,
prev_page => $prev_page,
per_page => $per_page,
);
print header(), $tmpl->output


<html>
<body>
<table border="1">
<TMPL_LOOP NAME="tmpl_data">
<tr>
<td><TMPL_VAR NAME="id"></td>
<td><TMPL_VAR NAME="data"></td>
</tr>
</TMPL_LOOP>
</table>
<br>
<TMPL_IF NAME="has_prev">
<a href='?offset=<TMPL_VAR NAME="prev_page">&per_page=<TMPL_VAR NAME="per_page">'>&lt;&lt;&nbsp;Previous</a>&nbsp;
</TMPL_IF>
<TMPL_LOOP NAME="all_pages">
<a href='?offset=<TMPL_VAR NAME="offset">&per_page=<TMPL_VAR NAME="per_page">'><TMPL_VAR NAME="page"></a>
</TMPL_LOOP>
<TMPL_IF NAME="has_next">
&nbsp;<a href='?offset=<TMPL_VAR NAME="next_page">&per_page=<TMPL_VAR NAME="per_page">'>Next&nbsp;&gt;&gt;</a>
</TMPL_IF>
</body>
</html>
Privod:
imho-no,
Уважаемый, я не знаю насколько часто Вы пьете пиво и где, Вы наверно не прочитали внимательно мой пост, пиво пить можно, но в бумажном пакете, как Вы думаете насколько это поможет бороться с пьянством? Лично я думаю что это просто увеличит количество мусора на улицах а так же прибыль у производителей бумажных пакетов.

никто так и не подтвержил и не опровергнул:

1) так можно пить безалкогольное пиво на улице?

2) видел ли кто-то что пьет кто-то со большого сткана или без этикетки? или в бумажном пакете (как написал автор топика) ? и зачем нужен бумажный пакет, туда пиво положить?

я это не видел нигде, я это как раз сейчас хотел сделать :)

в принципе не сверх сложно, так средненько, просто геморойно с sql запросами, jquery и т.д.

Всего: 2055