Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Problemy z PEAR/DB, ADODB, blobami w bazie i wyświetlaniem pdf
Forum PHP.pl > Forum > PHP
daniofantasy
Hej witam!

Piszę aplikację php, która ma wyświetlać pdfy, trzymane w polach BLOB w bazie danych. Założenia są takie:

1) Pliki, po kliknięciu w linka do danego pdfa wyświetlają się oknie przeglądarki (nie żadne okienko typu otwórz/zapisz, tylko koniecznie w oknie przeglądarki -> header content-desposition: inline; )

2) Pliki są przetrzymywane w bazie danych i w żadnym innym miejscu - w polach blob, a nie w żadnych plikach albo innych cudnych rozwiązaniach

3) Łączność z bazą danych rozwiązana jest przez warstwę abstrakcji do połączenia z bazą danych

4) Całość działa na templatach - każda strona serwisu jest edytowalna, jako jeden template - jak się pojawia coś, co jest pętlą - jest to wydzielonym blokiem w templacie

I powyższa specyfikacja niestety nie może ulec zmianie, ponieważ nie jest to zależne ode mnie...

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Ok - to teraz rozwiązania, na których się oparłem, pisząc ją

do łączności z bazą wybrałem PEAR DB (kompatybilne mniej więcej z MDB) - jak się zaczęły problemy, to kombinowałem również z ADODB i w razie czego jestem gotowy przepisać na nią całą aplikację... w tej chwili jest napisana pod PEAR DB

System templatów - PEAR HTML_Template_IT (są blokowe i łatwe do nauczenia)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Ok - a teraz problemy, z którymi się borykam i nie mogę na nie znaleźć rozwiązania, toteż zwracam się z prośbą o pomoc do was, drodzy forumowicze - raczej żadko zadaję pytania na forum, bo zazwyczaj szukam tak długo, aż znajdę jakieś rozwiązanie - ale tym razem nic mi nic nie podpowiada....

1) Problem jest taki, że ładuję sobie poprzez f_open i base64_encode pdfa do bloba w bazie i potem chcę go pobrać przez base64_decode z bazy danych i wyświetlam w nowym oknie przeglądarki headerami, ustawiając je na pdf. Ładowanie pdfa do bazy zrealizowałem w następujący sposób (poniższy kod używa PEAR/DB):

Kod
function dodaj_pdfa ($nazwa, $tmp_plik, $znak, $opis, $licznik, $data, $typ) {
    
    global $phptype;
    global $dbhost;
    global $database;
    global $username;
    global $password;    
    
    $dsn = "$phptype://$username:$password@$dbhost/$database";
    
    $db = DB::connect($dsn);    
    if (DB::isError($db)) {
        die($db->getMessage());
    }
    $nazwa_w_baze_sql = "insert into `pdfy` (`id`,`nazwa_pdf`,`znak`,`opis`,`pdf_data`,`typ`) values ('" . $licznik . "','" . $nazwa . "','" . $znak . "','" . $opis . "','" . $data ."','". $typ ."')";
    $plik_w_baze_sql = "insert into `pliki` (`id`,`plik_pdf`) values ('" . $licznik . "','" . $tmp_plik ."')";
    
    $nazwa_w_baze_query = $db->query($nazwa_w_baze_sql);

    if (DB::isError($nazwa_w_baze_query)) {
        $blad = $nazwa_w_baze_query->getMessage();
        die ('wystapił błąd w zapisywaniu nazwy pdfa do bazy, treść błędu: '. $blad);
    }    
    
    $plik_w_baze_query = $db->query($plik_w_baze_sql);
    
    if (DB::isError($plik_w_baze_query)) {
        $blad = $plik_w_baze_query->getMessage();
        die ('wystapił błąd w zapisywaniu pdfa do bazy, treść błędu: '. $blad);
    }    
    
    $db->disconnect;
    $db_wyjscie = array();
    $db_wyjscie[0] = 1;
    $db_wyjscie[1] = $ilosc;
    
    return $db_wyjscie;
}


i to jest w porządku - ładnie się ładuje, plik siedzi w bazie i tutaj raczej problemu nie ma - udało mi się go wyświetlić za pomocą następnego kodu, bez użycia warstwy abstrakcji, który działa :

Kod
function wyswietl_pdf($id) {

    $polaczenie = mysql_connect("www.mojastrona.pl", "mojlogin", "mojehaslo") or die (' Nie można połączyć się z databazą exclamation.gif! ');
    mysql_select_db("baza", $polaczenie) or die ('Nie można wybrać databazy exclamation.gif!');
    
    $zassany_pdf_query = mysql_query("select * from `pliki` where `id`='". $id ."' limit 1") or die ('<br><font color="red" face="arial" size="3">BŁĄD: APLIKACJA ZAKOŃCZYŁA SWOJE DZIAŁANIE.<br>Rodzaj błędu: nie mozna pobrac pliku z bazy <br> Błąd z mysql: ' . mysql_error() . '</font>');
    $zassany_pdf = mysql_fetch_assoc($zassany_pdf_query);
    $pdf_wyswietlany = base64_decode($zassany_pdf['plik_pdf']);
    
    mysql_close();
     header("Pragma: public");
     header("Expires: 0");
     header("Cache-Control: public");
     header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
     header("Content-type: application/pdf");
     header("Content-Transfer-Encoding: binary");
    
     echo $pdf_wyswietlany;
    ob_end_flush();
    
}


Więc zachwycony swoimi wynikami przepisałem sobie kod na warstwę abstrakcji (PEAR/DB) i zamiast oczekiwanego rezultatu na ekranie zobaczyłem Zonk, w postaci kodu źródłowego pdfa, którego przeglądarka nie zinterpretowała i wywaliła, jak leciało tongue.gif. Kod po przepisaniu:

Kod
function wyswietlacz_db($id){
    
    global $phptype;
    global $dbhost;
    global $database;
    global $username;
    global $password;
    
    $dsn = "$phptype://$username:$password@$dbhost/$database";
    $db = DB::connect($dsn);    
    if (DB::isError($db)) {
        die($db->getMessage());
    }
    
    $pokaz_query_sql = "select `plik_pdf` from `pliki` where `id` = ". $id ." limit 1";

    $pokaz_pdf_query = $db->query($pokaz_query_sql);
    
    if (DB::isError($pokaz_pdf_query)) {
        $blad = $pokaz_pdf_query->getMessage();
        die ('wystapił błąd w zapytaniu do bazy, nie można pobrać treści pliku. Treść błędu: '. $blad);
    }

    $pdf = $pokaz_pdf_query->fetchRow(DB_FETCHMODE_ASSOC);
    
    $pdf_wyswietlany = base64_decode($pdf['plik_pdf']);
    header('Pragma: public');
       header('Expires: 0');
        header('Cache-Control: public');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Content-type: application/pdf');
       header("Content-disposition: inline");
        header('Content-Transfer-Encoding: BASE64');
        echo $pdf_wyswietlany;
    ob_end_flush();
    ob_end_clean();
    $db->disconnect;
                     
}


kombinowałem na wszystkie strony i za nic nie mogłem znaleźć żadnego rozwiązania na mój problem... Potem stwierdziłem, że jak się nie da przy pomocy PEAR/DB, to może zmienię warstwę abstrakcji na inną i najwyżej przepiszę połączenia z bazą... Wybrałem ADODB i napisałem te funkcję na nowo, ale efekt taki sam - źródło pdfa na ekranie...

Kod
function wyswietlacz_pdf($id, $dod) {    
    
    global $phptype;
    global $dbhost;
    global $database;
    global $username;
    global $password;
    
    $dsn = "$phptype://$username:$password@$dbhost/$database";
    $db = ADONewConnection($dsn);
    $db->debug = false;
    
    if ($dod == 0) {
        $pdf_sql = "select `plik_pdf` from `pliki` where `id` = ". $id ." limit 1";
    }
    
    if ($dod == 1) {
        $pdf_sql = "select `plik_pdf` from `pliki_dod` where `id` = ". $id ." limit 1";
    }
    
    $db->SetFetchMode(ADODB_FETCH_ASSOC);
    $pdf = $db->execute($pdf_sql);
    if($db===false) die ('wystapił błąd w zapytaniu do bazy: '. $pdf_sql);

    $pdf_wyswietlany = base64_decode($pdf->fields['plik_pdf']);
    
    header('Pragma: public');
       header('Expires: 0');
        header('Cache-Control: public');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Content-type: application/pdf');
        header('Content-Transfer-Encoding: binary');
        
        echo $pdf_wyswietlany;
    ob_end_flush();

    $db->close();


Podejrzewam, że te warstwy abstrakcji "coś robią" z moim pdfem, przechowywanym w blobie w mysqlu i dlatego wywala mi kaszkę ze źródła pliku na ekran.... headery wydają się być ok - bo przecież z połączeniem wywołanym z php poprzez mysql_query, to działa - kombinowałem też bez rezultatów z opcjami content-transfer-encoding z binary na 7bit, 8bit, base64 i BASE64... próbowałem też dorzucać nagłówki content-desposition: inline, attachment - z tym że attachment być nie może, ponieważ pdfy muszą się wyświetlać pod przegladarką, a nie za pomocą zewnętrznego programu... więc nie wiem, co w nich można jeszcze zmienić, aby mi tego pdfa wyświetliło....

Inną rzeczą, która mi przychodzi do głowy może być złe przypisanie danych pobranych z bazy do tablicy, bo jak zrobiłem wcześniej bez warstwy abstrakcji mysql_fetch_array(), to też mi wywalało źródło - dopiero przypisanie do tablicy asocjacyjnej, mysql_fetch_assoc dało żądany rezultat w postaci prawidłowo wyświetlonego pdfa - toteż nie wiem, czy nie popełniam błędu przy ustawianiu fetch_mode na assoc w przypadku warstw abstrakcji - może tam powinno być coś innego? - też tego wykminić nie mogę....

chyba, że jest błąd przy ładowaniu pliku, ale raczej nie, bo przecież z polecenia wykonanego pod mysqlem się wyświetla poprawnie, jedynie jest problem przy warstwach abstrakcji...

A niestety z warstw abstrakcji zrezygnować nie mogę, ponieważ mam to narzucone z góry...


ok - drugi problem, który mam, to templaty, a dokładniej pętla wykonana na jednym bloku, w którym alternatywnie jest ładowany blok z inną treścią podczas edycji... - opisuję go w innym poście

Jeżeli ktoś zna jakikolwiek sposób na rozwiązanie któregokolwiek z powyższych problemów, to proszę o posta w tej sprawie winksmiley.jpg jakakolwiek sensowna pomoc mile widziana. Będę za każdą podpowiedź bardzo wdzięczny, ponieważ już piszę z opóźnieniem i właściwie zostały mi te dwa błędy do rozwiązania i nie mogę sobie z nimi dać rady...

Pozdrawiam,

Daniofantasy

Nie bardzo wiem, od czego zacząć - manuale tych klas, co używam też mi niewiele mówią - ma ktoś jakiś pomysł?

minęło kilka dni i żadnych postępów... ma ktoś może jakiś pomysł...?
hidee
dodaj nagłówek:
header('Content-Type: application/pdf'); //może mieć znaczenie wielkość literki t w Content-Type
header('Content-Disposition: attachment; filename=nazwapliku.pdf');

Sprawdź również co dzieje się pod Operą, Fx oraz badzIEwiem. IE7 ma u mnie problem z wysyłą Excelów. W IE6 jest ok.
daniofantasy
Te rady, które mi dałeś nic nie pomogły, bo z headerami kombinowałem, co się dało, ale problem leżał w tym, że includowałem sobie pliczek z dsnem do bazy i tam miałem spacje PO tagu zamykającym kod php ?> i nie zwróciłem na to uwagi i stąd tyle czasu stracone... ech.. człowiek uczy się całe życie...

W każdym razie dzięki za odp i pozdrawiam,

Daniofantasy
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.