download.bg
 Вход Списание  Новини  Програми  Статии  Форум  Чат   Абонамент  Топ95   Архив 

Картинка в БД (php MySQL)

<1 2 >

Автор
Съобщение
insecteater
Пет, 19.10.07, 14:08
Друг начин, който ми харесва и ползвам, касае прикачането на няколко картинки към даден запис от база данни.
За целта ни трябва единствено дефинирано поле от някакъв целочислен тип, в която да съхраняваме
информацията. Идеята е, на базата на това число чрез побитови операции да сравняваме и определяме с кои точно картинки разполагаме.

ДЕФИНИРАНЕ НА ПОЛЕТО ЗА БАЗАТА ДАННИ

Представи си, че даден потребител има портретна снимка, аватар и няколко фотоснимки. Да приемем, че максималният им общ брой не може да бъде повече от 10
На базата на тази информация правим следното:
повдигаме числото 2 на степен 10, което прави 1024. Най близкият целочислен тип до тази стойност в MySQL е SMALLINT UNSIGNED

Съответно си правим и табличката:
$Query = "CREATE TABLE IF NOT EXISTS Users (
  Id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY (Id), /* Няма нужда от обяснение */
  UserName VARCHAR(255), /* Потребителско име */
  Mail VARCHAR(127) DEFAULT NULL, /* Електронна поща на потребителя */
  Description TEXT DEFAULT NULL, /* Описание на потребителя */
  Pictures SMALLINT UNSIGNED, /* Информация за картинките на потребителя */
  INDEX(UserName));";

SMALLINT UNSIGNED е в обхвата от 0 to 65535, така че, можем да имаме максимален брой от 15 различни снимки за един потребител (2 на степен 16 = 65536)

ИЗВЛИЧАНЕ НА ИНФОРМАЦИЯТА

Сега малко за побитовата операция & ("и")
Нека имаме едно двоично число - 000000000110101 - (това число е равно на десетичното 53)
Да разгледаме къде имаме единици:
 - най вдясно имаме числото 1, това означава, че потребителят е качил портретната си снимка
 - след него на втора позиция (от дясно на ляво) имаме числото 0, това означава, че потребителят НЕ е качил аватар
 - от там нататък, имаме три единици, което означава, че потребителят е качил три фотоснимки.

Да си представим, че искаме да покажем фотоснимките на потребителя - правим си т. нар. "маска".
Интересува ни дали на петата позиция (от дясно на ляво) има единица
Възможността беше най много за 15 картинки, така че маската трябва да е от 15 позиции: 000000000010000
(десетично 16 - което между другото може лесно да се изчисли, като знаем коя позиция ни трябва: 2 на степен (5-1))
Мястото на нулите в маската, показва, че не се интересуваме какви са числата на тези позиции.
Нека да сложим едно под друго двете числа:
000000000010000 - маска
000000000110101 - число идващо от базата данни (десетично 53)
Резултатът от операцията & (побитово "и")ще бъде
000000000010000 (десетично 16)
Сам по себе си фактът, че това число не е 0 (заради съществуващата единица) показва, че потребителят има сложена фотоснимка на тази позиция. Можем разбира се да извикаме снимките като видим дали съществуват с функцията file_exist, но не е препоръчително, понеже тя се обръща към операционната система и става бавно.

Ето например как можем да генерираме списъка с фотоснимките на базата на полето Pictures
<?php
//Приемаме, че $UserId, $UserName и $Pictures са вече извлечени от базата дани
 
$Html = '';
//Започваме цикъла от 2, понеже снимките се разполагат от вторият бит нататък (без да го включва)
for ($i = 2; $i <= 14; ++$i) {
    $Num = $i - 1; //Позиция на фотоснимката
    //Генериране на необходимата ни маска за текущата позиция на фотоснимката
    $Mask = pow(2, $i); 
    //Извличане на информацията, дали поредната фотоснимка е качена
    $Pic =  $Pictures & $Mask;
    //Генериране на html код за изображението, ако то е налично
    if ($Pic) $Html .= "$Num - <img src=\"images/pic_$UserId-$i.jpg\" alt=\"$UserName\" /><br />";
}
//Показване на html кода
echo $Html;
?>

ПРОМЯНА НА ИНФОРМАЦИЯТА

Обратната операция - слагане на информацията за това, че потребителят току що е качил снимка, става с побитовото "изключващо или" - "^"
Например искаме да зададем нова стойност, която да отразява, че потребителят току що е качил снимка на 11-та позиция - маската ни ще бъде: 2 на степен (11-1) което е равно на 1024
000010000000000 - маска (десетично 1024)
000000000110101 - число идващо от базата данни (десетично 53)
Резултатът от операцията ^ (изключващо или ) ще бъде
000010000110101 (десетично 1077)

Или иначе казано
$Position = 11;
$Pictures = $Pictures ^ pow(2, ($Postition-1));

Така новата стойност 1077 записваме в базата данни.

ПРЕДИМСТВА

Слагането на самите картинки в базата данни коства много ресурси при последваща работа с тази база данни. При малък брой потребители, това може и да не се забележи много, но при нарастване на броя потребители и съответно техните снимки, всякакво четене от такава база данни ще бъде излишно натоварено.

От друга страна, предложеният начин за съхраняване информацията за картинки е много по-икономичен откъм компютърни ресурси:
- Съхранява се само едно число
- Размера на картинките по никакъв начин не влияе на бързодействието на базата данни
- Пести се процесорно време и памет при извличане на картинките и пращането им към браузъра, понеже се избягва допълнителна конекция и претърсване на базата данни в допълнителният скрипт за изпращане на изображението към браузъра

НЕДОСТАТЪЦИ

- За начинаещите програмисти алгоритъмът е сложен. Но този аргумент напълно отпада, когато се преследва високо бързодействие или се работи с много записи.
- Възможност от "десинхронизация" - т.е. в базата данни числото да показва че такава картинка съществува, а физически да я няма качена в съответната папка, поради някаква грешка например. Това лесно се избягва със съвсем малко допълнителен код.
- Ограничен брой възможни позиции - 63 заради най големият възможен целочислен тип - BIGINT UNSIGNED. Съществуват обаче заобиколни начини, в основата си лежащи на този подход
- Картинките не са защитени от механизма за сигурност на базата данни. (потребител и парола)

ЗАБЕЛЕЖКИ
Кодът който съм писал не съм го тествал. Писал съм го единствено с цел обяснение на самият метод. Ако имате забележки или предложения, обаждайте. Възможно е да съм сгрешил някъде в някое число, но идеята все пак е да се изясни същността на метода.

anonymous
Пет, 19.10.07, 14:23
Картинките са наи-силния забавител и много ругатни ще отнесеш от онези ,които искат да влязат.
направо е мъчение.
anonymous
Пет, 19.10.07, 17:38

RE: Картинка в БД (php MySQL)

...
Друг начин, който ми харесва и ползвам, касае прикачането на няколко картинки към даден запис от база данни.
За целта ни трябва единствено дефинирано поле от някакъв целочислен тип, в която да съхраняваме
информацията. Идеята е, на базата на това число чрез побитови операции да сравняваме и определяме с кои точно картинки разполагаме.
...
(insecteater) Много ти благодаря за изчерпателния отговор.
редактиран от anonymous на 19.10.07 17:39
anonymous
Пет, 26.10.07, 13:59
Защо не се визуализира картинка????
<?php
 
 	$pic=$HTTP_POST_VARS['pic'];
	$id=$HTTP_POST_VARS['id'];
 
	  @ $db = mysql_pconnect('localhost', 'root','');
 
	  if (!$db)
	  {
		 echo 'Базата данни не е открита.';
		 exit;
	  }
	   mysql_select_db('new');
		 $query = "select * from potrebitel ";
		 $result = mysql_query($query);
		 $num_results = mysql_num_rows($result);
 
	echo '<table border=0 BORDERCOLOR="F3CC99" CELLPADDING=5 CELLSPACING=0><tr><td>';
		 for ($i=0; $i <$num_results; $i++)
		 {
			$row = mysql_fetch_array($result);
			echo '<table border=1 BORDERCOLOR="F3CC99" CELLPADDING=5 CELLSPACING=0><tr><td width=900><font color=003366><strong> снимка: </strong>';
			echo htmlspecialchars(stripslashes($row['<img src="images/'.($_GET['id']*1).".jpg\" alt=\"$pic\" />"]));
			echo '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>id: </strong>';
			echo stripslashes($row['id']);
			echo '</td></tr></table></font>';
	     }
	    echo '</td></tr></table>';
?>

db=new
table=potrebitel
    id
    pic

insecteater
Пет, 26.10.07, 14:38
$row = mysql_fetch_array($result);
$row става смесен масив, съдържащ двойките: име на колона - стойност на полето за текущия ред

Реда ти
echo htmlspecialchars(stripslashes($row['<img src="images/'.($_GET['id']*1).".jpg\" alt=\"$pic\" />"]));

Е безсмислен. Просто колона с такова име <img src="images/'.($_GET['id']*1).".jpg\" alt=\"$pic\" /> със сигурност нямаш в таблицата си в базата данни.

По -скоро ще е нещо такова:
echo '<img src="images/'.$row['id'].'.jpg" alt="'.$pic.'" />';
Ако ще правиш обезопасяване на данни сhtmlspecialchars и stripslashes в случая го прави само върху $pic, макар и да си нямам идея от къде го вземаш. Очевидно не е от базата данни, а от някаква POST заявка.

Редакция, между другото скрипта както е направен, ще покаже картинките на ВСИЧКИ потребители в базата данни. Представям си какво ще е ако са няколкостотин

редактиран от insecteater на 26.10.07 14:41
anonymous
Пон, 29.10.07, 13:22

RE: Картинка в БД (php MySQL)

” Редакция, между другото скрипта както е направен, ще покаже картинките на ВСИЧКИ потребители в базата данни. Представям си какво ще е ако са няколкостотин „

Да знам. ... и отново благодаря за помощта!

anonymous
Пет, 28.03.08, 16:10
Добре да попитам и аз тогава, понеже спадам към начинаещите и твоят метод като че ли не ми стана от край до край ясен...
Аз правя нещо подобно, имам адски много потребители, които могат да уплоадват между 8 и 32 снимки.
Имам таблица pics съдържаща PK,user_id, полета от pic1 do pic32. Разбира се нямам никакво намерение да качвам снимките в базата, а само имената на файловете, примерно 3.jpg е такъв файл.

Но идеята ми се оказа малко сложна за моите възможности...Възможно ли е с една и съща форма да правя следните неща:
1. Upload на снимка - ако полето в базата е празно, да преименува снимката (комбинация от полето в базата, вкоето ще се запише снимката и user_id или PK (за един и същи потербител те са ми уникални)), да я качи в папка pics, да ми прави лог в папка logs, да записва новото име на снимката в базата
2. Промяна на качена снимка - да ми намира по полето, в което искам да я кача в базата името на файла, да преименува новата снимка с това име и да я презапише върху старата в папка pics, да ми създаде лог-а
3. Изтриване на снимка (отделен бутон във формата) - дами намира снимката по поле в базата, да затрива записа там и да я изтрива от папка pics, в този случай май не ми е необходим лог

Има ли смисъл да си мъча галавата с това, просто не знам, занимавам се с php 3-и месец, до преди това дори не го бях виждала... Струва ми се почти непосилно да стане, а не съм видяла до сега реализация на подобен upload, колкото и да рових в нета... Ако могат да ми се дадат напътствия и да ми се обясни това как "ще ми омаже базата", или все пак не е лошо като идея...

<1 2 >

Коментар

за нас | за разработчици | за реклама | станете автори | in english  © 1998-2024   Experta Ltd.