Autor Zpráva
emissary
Profil
Zdravím Vás,

trocha sa trápim s PDO. Vedel by mi niekto poradiť? Proste mi to nefunguje.

Tabuľka v databáze:

CREATE TABLE  `kapitolasest`.`jpeg-image` (
`id` INT( 5 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`bindata` LONGBLOB NOT NULL
) ENGINE = MYISAM 

PHP Skript uložený ako image.php:
$user = 'kapitolasest';
$password = 'kapitolasest';
$strDSN = 'mysql:host=localhost; dbname=kapitolasest';
$id = 1;


    $objPDO = new PDO($strDSN, $user, $password);
    $strQuery = "SELECT bindata FROM jpeg-image WHERE id = :imageid";
    $stmt = $objPDO->prepare($strQuery);
    $stmt->bindParam(':imageid', $GET["id"], PDO::PARAM_INT);
    $stmt->execute();
    $stmt->bindColumn(1, $binData, PDO::PARAM_LOB);
    $stmt->fetch(PDO::FETCH_BOUND);
    
    header("Content-Type: image/jpeg");
    fpassthru($binData);
    exit(0);

A nakoniec jednoduchá stránka s jediným objektom:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Jpeg-image</title>
</head>

<body>

<img src="image.php?id=1"  />
</body>
</html>


V čom robím chybu, keď mi nechce obrázok načítať?
Alphard
Profil
Ten příklad vypadá dost manuálově. Nejlepší bude zakomentovat tu hlavičku obrázku, zobrazit si přímo image.php?id=1 a přečíst si případnou chybu.
emissary
Profil
Alphard:
To som skúšal...aj priamo zadefinovať ID... Ja ešte len objavujem krásu PHP. Takže som taký začiatočník.


Skúšal som s ním už všetko možné, ale žiadnu chybu mi to nevyhodí. Ten kód mám momentálne takto uložený v protest3.php:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Jpeg-image</title>
</head>

<body>

<?php
error_reporting(E_ALL | E_NOTICE);
ini_set('display_errors', 'On');
ini_set('html_errors', 'On');


$user = 'kapitolasest';
$password = 'kapitolasest';
$strDSN = 'mysql:host=localhost; dbname=kapitolasest';
//$id = 1;

try {
    $objPDO = new PDO($strDSN, $user, $password);
    print "Úspešne pripojené...\n";
    $strQuery = "SELECT bindata FROM jpeg-image WHERE id = :imageid";
    $stmt = $objPDO->prepare($strQuery);
    $stmt->bindParam(':imageid', $GET["id"], PDO::PARAM_INT);
    $stmt->execute();
    $stmt->bindColumn(1, $binData, PDO::PARAM_LOB);
    $stmt->fetch(PDO::FETCH_BOUND);
    
    header("Content-Type: image/jpeg");
    fpassthru($binData);
    exit(0);
    
    
} catch (PDOException $e) {
    echo "Došlo k chybe pri pokuse o pripojenie: ". $e->getMessage(). "<br />\n";
    list($strCode, $strCode2, $strInfo) = $objPDO->errorInfo();
    print "PDO: - kód chyby: '$strCode', <br /> - kód chyby ovládača: '$strCode2', <br /> - popis chyby: '$strInfo'";
    if($objStatement instanceof PDOStatement) {
        list($strCode, $strCode2, $strInfo) = $objStatement->errorInfo();
        print "<br /><br />PDOSattement: - kód chyby '$strCode', <br /> - kód chyby ovládača: '$strCode2', <br /> - popis chyby: '$strInfo' ";
    };
    exit(0);
}



?>

<img src="pdotest3.php?id=1"  />
</body>
</html>
SwimX
Profil
emissary:
to druhé by mělo vyhodit chybu, protože pošleš HTML kód a pak hlavičku, že to je image/jpeg.

Proč to vlastně děláš takle? Většinou je lepší nápad mít v DB jen ID a soubory na filesystemu.
emissary
Profil
SwimX:

Nevyhodí to vôbec nič... ale môžem tu hlavičku opraviť. Nie je problém. A viem ako sa to robí... toto je len čisto z študijných dôvodov :)
Alphard
Profil
Z dostupných informací mi není jasné, co jste zkoušel a co jste zjistil. Měl jsem na mysli, abyste zkusil něco v tomto smyslu, nic víc. Pokud máte defaultně zakázaný výpis chyb, tak dodat error_reporting(E_ALL);.

// připojení k db
$id = 1; 
 
$objPDO = new PDO($strDSN, $user, $password);
$strQuery = "SELECT bindata FROM jpeg-image WHERE id = :imageid";
$stmt = $objPDO->prepare($strQuery);
$stmt->bindParam(':imageid', $id, PDO::PARAM_INT); // když už je definované na 2. řádku, ale musí v db existovat obrázek s id 1
$stmt->execute();
$stmt->bindColumn(1, $binData, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);

//header("Content-Type: image/jpeg");
fpassthru($binData);
emissary
Profil
Alphard:


Myslím že na začiatku druhého príkladu je niečo takéto:

error_reporting(E_ALL | E_NOTICE);
ini_set('display_errors', 'On');
ini_set('html_errors', 'On');


Teraz je ten kód uložený v pdotest3.php a presne v tomto znení:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="image/jpeg; charset=utf-8" />
<title>Jpeg-image</title>
</head>

<body>

<?php
error_reporting(E_ALL | E_NOTICE);
ini_set('display_errors', 'On');
ini_set('html_errors', 'On');


$user = 'kapitolasest';
$password = 'kapitolasest';
$strDSN = 'mysql:host=localhost; dbname=kapitolasest';
$id = 1;

try {
    $objPDO = new PDO($strDSN, $user, $password);
    print "Úspešne pripojené...\n";
    $strQuery = "SELECT bindata FROM jpeg-image WHERE id = :imageid";
    $stmt = $objPDO->prepare($strQuery);
    $stmt->bindParam(':imageid', $id, PDO::PARAM_INT);
    $stmt->execute();
    $stmt->bindColumn(1, $binData, PDO::PARAM_LOB);
    $stmt->fetch(PDO::FETCH_BOUND);
    
    //header("Content-Type: image/jpeg");
    fpassthru($binData);
    exit(0);
    
    
} catch (PDOException $e) {
    echo "Došlo k chybe pri pokuse o pripojenie: ". $e->getMessage(). "<br />\n";
    list($strCode, $strCode2, $strInfo) = $objPDO->errorInfo();
    print "PDO: - kód chyby: '$strCode', <br /> - kód chyby ovládača: '$strCode2', <br /> - popis chyby: '$strInfo'";
    if($objStatement instanceof PDOStatement) {
        list($strCode, $strCode2, $strInfo) = $objStatement->errorInfo();
        print "<br /><br />PDOSattement: - kód chyby '$strCode', <br /> - kód chyby ovládača: '$strCode2', <br /> - popis chyby: '$strInfo' ";
    };
    exit(0);
}



?>

<img src="pdotest3.php"  />

</body>
</html>


Výsledok je takýto:

Úspešne pripojené...
Warning: fpassthru() expects parameter 1 to be resource, null given in /data/www/prco.sk/prco.sk/www/14_pdo/pdotest3.php on line 32


ak odkomentujem //header("Content-Type: image/jpeg");, tak to zas nič nevyhodí, len "obrys nenačítaného obrázka...

A áno, obrázok s ID 1 sa nachádza v databáze.
Alphard
Profil
emissary:
Warning: fpassthru() expects parameter 1 to be resource, null given in /data/www/prco.sk/prco.sk/www/14_pdo/pdotest3.php on line 32
Tohle je ta klíčová věc, nepředávají se vám data. A když se tak dívám na název tabulky, nelíbí se mi tam tam ta pomlčka, zkuste ten dotaz spustit v nějakém adminu. Třeba pomocou zpětné apostrofy.
emissary
Profil
Alphard:


Začínam byť zúfalý... Vytvoril som novú tabuľku ([plne identickú ako predošlá), len som ju pomenoval na jpeg. Ale chyba je rovnaká, možno je to zle uložené v databáze. Asi sa tie dáta v tabuľke ukladajú v nejako zvláštnom formáte, ktorý nevie prečítať.

CREATE TABLE `kapitolasest`.`jpeg` (
`id` INT( 5 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`bindata` LONGBLOB NOT NULL
) ENGINE = MYISAM

V phpmyadminovi ten dotaz prebehne korektne.


emissary:
Nemáte skype?
okolojsoucí
Profil
emissary:
emissary:
Nemáte skype?
To se ptáš sám sebe?

Jinak prakticky bys porušoval pravidla kdybys chtěl odpověď jinak než zde v diskuzi
Pravidla diskuse JPW a doporučení » 7. Nechtějte, aby vám lidi posílali odpověď mailem. Je-li veřejně dostupný dotaz, má být veřejně dostupná i odpověď.
emissary
Profil
okolojsoucí:

Nie som si vedomý toho, že by som akýmkoľvek spôsobom porušoval pravidlá tohto fóra. Mám záujem spoznávať ľudí, ktorí rozumejú tejto problematike ďaleko viac ako ja. A z toho dôvodu hľadám aj iné formy komunikácie, ktoré presahujú možnosti tohto fóra. Skôr by som považoval tvoj príspevok, v tejto téme, za porušenie pravidiel. Keďže tvoja odpoveď sa ani len okrajovo nedotkla problému o ktorom sa tu vedie diskusia. Pekný večer...
Mike8748
Profil
emissary:
pokud dobře chápu, tak v databázi v sloupci bindata je uložený obrázek jako takový (usuzuji z datového typu longblob) takže nějak netuším proč tam používáš funkci fpassthru která je určená pro práci se soubory.

ty binarní data potřebuješ vypsat, tak zkus print nebo echo
emissary
Profil
Mike8748:
Hmm.... píšu tam doslovne,


V tomto prípade metoda bindColumn rika PDO, aby se první sloupec(úplne vlevo) dat vracených databází uložil do promenné binData - uložení dat do promenné zpusobí každé volání metody fetch sloužící pro načtení rádku vracených dat. Tím, že jako dátový typ uvedete PDO::PARAM_LOB, uloží metoda fetch data do promenné s využitím nejbliťší aproximace velkého objektu v PHP - konkrétne streamu.

Stream souboru je možné v PHP odeslat prímo na standardní výstup pomocí funkce fpassthru - a presne to udeláte pro predání binárnich dat tvorících obrázek prímo prohlížeči. Ješte predtím se odešle vhodný typ MIME pro obrázek.


takže odskúšal som print a aj echo. Pri NEzakomentovanom príkaze
header("Content-Type: image/jpeg");
nie je žiadna zmena. Opäť obrys nenačítaného obrázka. Pri zakomentovanom //header("Content-Type: image/jpeg"); to vypíše spústa nezmyselných dát. "Úspešne pripojené... ����JFIF��*��ICC_PROFILE lcmsmntrRGB XYZ •�)9acspAPPL���-lcms desc�^cprt\ wtpthbkpt|rXYZ�gXYZ�bXYZ�rTRC�@gTRC�@bTRC�@descc2textFBXYZ ���-XYZ 3�XYZ o�8��XYZ b����XYZ $����curv��c�k �?Q4!�)�2;... "
Mike8748
Profil
emissary:
ok, tím se dostáváme k zásadnímu problému

ten tvůj výpis začíná textem "Úspešne pripojené..." což je něco co způsobí že prohlížeč nepozná data jako obrázek a proto se ti nezobrazí.
skript image.php (tak jak je zde uvedený) ten text neobsahuje, tedy pokud to není již v databázi uložené. pokud ten text sám někde vypisuješ, tak to nedělej.

jinak, při použití header("Content-Type: image/jpeg"); ta tvoje "nesmyslná" data budou správně zobrazena jako obrázek (pokud teda nebudou poškozena nějakým dalším výpisem)
emissary
Profil
Mike8748:

Tak som spravil z celého toho skriptu toto:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="image/jpeg; charset=utf-8" />
<title>Jpeg</title>
</head>

<body>
<?php
$user = 'kapitolasest';
$password = 'kapitolasest';
$strDSN = 'mysql:host=localhost; dbname=kapitolasest';
$id = 1;

    $objPDO = new PDO($strDSN, $user, $password);
    $strQuery = "SELECT `bindata` FROM `jpeg` WHERE id = :imageid";
    $stmt = $objPDO->prepare($strQuery);
    $stmt->bindParam(':imageid', $id, PDO::PARAM_INT);
    $stmt->execute();
    $stmt->bindColumn(1, $binData, PDO::PARAM_LOB);
    $stmt->fetch(PDO::FETCH_BOUND);
    
    header("Content-Type: image/jpeg");
    fpassthru($binData);
    exit(0);
?>

<img src="test2.php"  />
</body>
</html>



Ale stále ten istý problém. Teraz keď zakomentujem //header("Content-Type: image/jpeg") tak sa stratí aj ten nenačítaný obrys obrázka. Inak je tam toto: http://www.prco.sk/14_pdo/test2.php


Ten text sa nenachádzal v databázy... ten som mal pre "kontrolu". Už je preč.
Mike8748
Profil
emissary:
tím že si odstranil ten kontrolní výpis si měl skončit. ty dva soubory nemůžeš (alespoň ne takto jednoduše) míchat dohromady

vrať se k tomu že budeš mít opět stránkus html,
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="image/jpeg; charset=utf-8" />
<title>Jpeg</title>
</head>
 
<body>
<img src="image.php" />
</body>
</html>

a skript image.php kde bude
<?php
$user = 'kapitolasest';
$password = 'kapitolasest';
$strDSN = 'mysql:host=localhost; dbname=kapitolasest';
$id = 1;
 
    $objPDO = new PDO($strDSN, $user, $password);
    $strQuery = "SELECT `bindata` FROM `jpeg` WHERE id = :imageid";
    $stmt = $objPDO->prepare($strQuery);
    $stmt->bindParam(':imageid', $id, PDO::PARAM_INT);
    $stmt->execute();
    $stmt->bindColumn(1, $binData, PDO::PARAM_LOB);
    $stmt->fetch(PDO::FETCH_BOUND);
    
    header("Content-Type: image/jpeg");
    fpassthru($binData);
emissary
Profil
Mike8748:

Ďakujem Ti moc, vyriešené. Problém bol teda skutočne v fpassthru($binData); ktorý sme vymenili za echo($binData);

funkčná verzia kódu image.php:

<
<?php

$user = 'user';
$password = 'password';
$strDSN = 'mysql:host=localhost; dbname=mydb';

$objPDO = new PDO($strDSN, $user, $password);
$strQuery = "SELECT `bindata` FROM `jpeg` WHERE id = :imageid";
$stmt = $objPDO->prepare($strQuery);
$stmt->bindParam(':imageid', $_GET["id"], PDO::PARAM_INT);
$stmt->execute();
$stmt->bindColumn(1, $binData, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
    
header("Content-Type: image/jpeg");
echo($binData);  //NEPOUZIVAT fpassthru($binData);
exit(0);
?

testimage.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Jpeg-image</title>
</head>

<body>

<img src="image.php?id=1"  />  

</body>
</html>
Alphard
Profil
emissary [#15]:
Obsahem toho souboru (obrázek test2.php) je následující kód. Z prvního příspěvku jsem měl pocit, že docela rozumíte principu, postupně se mi ale zdá, že kód lepíte naprosto náhodně. Uvědomte si, že obrázek se skládá z binárních dat, musíte zajistit, aby se vypsala právě jen ta binární data z databáze a nic jiného (žádné html, žádné kontrolní výpisy, chybové hlášky a ukončovací ?> na konec souboru bych taky nedával). Konkrétní provedení viz [#16] Mike8748 (jen tam dočasně chybí to předávání parametru v $_GET, ale to už od začátku).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="image/jpeg; charset=utf-8" />
<title>Jpeg</title>
</head>

<body>
<br />
<b>Warning</b>:  fpassthru() expects parameter 1 to be resource, string given in <b>/data/www/prco.sk/prco.sk/www/14_pdo/test2.php</b> on line <b>31</b><br />

Nemáte skype?
Berte to tak, že nejsem online technická podpora. Na diskusi se snažím pomáhat, když mám čas, které bohužel nemám mnoho. Diskuse není chat, nad odpovědmi byste se měl zamyslet, vyzkoušet je, dohledat další informace a pak až se znovu ptát.

Mike8748 [#12]:
Možná už to bylo nalezeno, v manuálu se tomu věnuje stránka www.php.net/manual/en/pdo.lobs.php. Sám bych rozumně velké obrázky také asi vypisoval klasicky přes echo, ale není důvod bránit se práci se streamy.

emissary [#17]:
Problém bol teda skutočne v fpassthru($binData); ktorý sme vymenili za echo($binData);
Nebyl, ta funkce fungovala správně. Problém byl ve všem okolo.
emissary
Profil
Alphard:

emissary [#17]:
„Problém bol teda skutočne v fpassthru($binData); ktorý sme vymenili za echo($binData);“
Nebyl, ta funkce fungovala správně. Problém byl ve všem oko




Problém tým bol skutočne vyriešený, pri použití funkcie fpassthru($binData) kód nefunguje, môžte si to vyskúšať. Ak by sa Vám to podarilo, tak ma informujte. ďakujem
Alphard
Profil
emissary [#19]:
Příspěvek [#13] je důkaz, že výpis binárních dat fungoval, víc to neřeším. Vy teď máte fungující script, o to vám od začátku šlo, takže vše v pořádku. Jen by vhodný závěr z toho vlákna byl, že při výpisu obrázku se nemá vypisovat žádný jiný bordel, nikoliv, že byl problém v fpassthru.
emissary
Profil
Alphard:
emissary [#19]:
Příspěvek [#13] je důkaz, že výpis binárních dat fungoval, víc to neřeším. Vy teď máte fungující script, o to vám od začátku šlo, takže vše v pořádku. Jen by vhodný závěr z toho vlákna byl, že při výpisu obrázku se nemá vypisovat žádný jiný bordel, nikoliv, že byl problém v fpassthru.


To vy tvrdíte, že chyba bola v "bordeli". Ja tvrdím, že chyba bola v fpasstru. My sme dokázali rozbehnúť ten kód len s echo. Ak poznáte riešenie pre fpasstru, tak sa mile rád priučim. Fakt je ten, že ten kód v takej forme ako je teraz funguje len s echo.

Mne to funguje aj s týmto bordelom. Len si treba všimnúť riadok 21 a 22.

<?php
error_reporting(E_ALL | E_NOTICE);
ini_set('display_errors', 'On');
ini_set('html_errors', 'On');


$user = 'kapitolasest';
$password = 'kapitolasest';
$strDSN = 'mysql:host=localhost; dbname=kapitolasest';

try {
    $objPDO = new PDO($strDSN, $user, $password);
    $strQuery = "SELECT `bindata` FROM `jpeg` WHERE id = :imageid";
    $stmt = $objPDO->prepare($strQuery);
    $stmt->bindParam(':imageid', $_GET["id"], PDO::PARAM_INT);
    $stmt->execute();
    $stmt->bindColumn(1, $binData, PDO::PARAM_LOB);
    $stmt->fetch(PDO::FETCH_BOUND);
    
    header("Content-Type: image/jpeg");
    echo ($binData);
    //fpassthru($binData);
    exit(0);
    
    
} catch (PDOException $e) {
    echo "Došlo k chybe pri pokuse o pripojenie: ". $e->getMessage(). "<br />\n";
    list($strCode, $strCode2, $strInfo) = $objPDO->errorInfo();
    print "PDO: - kód chyby: '$strCode', <br /> - kód chyby ovládača: '$strCode2', <br /> - popis chyby: '$strInfo'";
    if($objStatement instanceof PDOStatement) {
        list($strCode, $strCode2, $strInfo) = $objStatement->errorInfo();
        print "<br /><br />PDOSattement: - kód chyby '$strCode', <br /> - kód chyby ovládača: '$strCode2', <br /> - popis chyby: '$strInfo' ";
    };
    exit(0);
}

?>

Ale je zrejmé, že tá kontrola try catch je úplne k ničomu. To nepopieram. Len hovorím o faktoch. Takže dovolím si uzavrieť toto téma tým, že príkaz fpassthru($binData); Nepracuje korektne. Dôvod nepoznám. Zato echo vyriešilo tento problém. Ďakujem všetkým, čo sa zapojili.
Mike8748
Profil
problém byl v tom že PDO::PARAM_LOB neudělalo přesně to co mělo.
PDO vracelo data jako string (tedy obsah BLOB sloupce), ne jako stream.

jde o problém existující již 7 let, viz https://bugs.php.net/bug.php?id=40913

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: