| Autor | Zpráva | ||
|---|---|---|---|
| maycza Profil |
#1 · Zasláno: 23. 3. 2015, 08:21:00
Zdravím,
chtěl bych se zeptat, máte někdo zkušenosti s nahráváním souborů do ms sql databáze? Data ukládám do sloupce typu varbinary(max). Mám kód:
$content=file_get_contents($_FILES["soubor"]["tmp_name"]);
$content=base64_encode($content);
$q="INSERT INTO files (name,size,type,content,znak)VALUES('".htmlspecialchars($soubor_name)."','$soubor_size','$soubor_typ',CONVERT(varbinary(MAX), '$content'),'c')";
$d=odbc_exec($db, $q);Data se bez problémů uloží. Problém nastává při výpisu dat, pro který používám následující kód: $db = odbc_connect('Driver=TDS;Server=nejakyServer;', 'jmeno', 'heslo');
if($db === false) {echo "Chyba připojení k databázi";}
$q=odbc_exec($db,"SELECT name, type, size, CONVERT(varbinary(MAX),content) AS content FROM files WHERE id=".$_GET["id"]);
while($r=odbc_fetch_array($q)){
$name=$r["name"];
$size=$r["size"];
$velikost=$r["content"];
$type=$r["type"];
$content=base64_decode($r["content"]);
}
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified
header("Content-length: " . $size);
header("Content-type: " . $type);
header("Content-Disposition: attachment; filename={$name}");
header("Content-Transfer-Encoding: binary");
print($content);Dalo by se říct, že všechno funguje, ale... pokud jsou data < 8kB vše je ok, pokud jsou větší, vypíše se jen část (do 8kB) a tím pádem se data stávají nečitelnými. Když si nechám vypsat jen surová data ze sloupce content, vypíše se vždy jen jejich část, vždy se to utne na stejném místě (omezení 46000). Pokud v databázi spustím dotaz SELECT LEN(content) FROM tabulka zjistím, že soubor má mnohem víc znaků než 46000.
Zjistil jsem, že MS SQL managenet studio má záměrně omezení pro výpis dat 8kB / 46000 znaků, čemuž rozumím, proč ale nemůžu z databáze dostat celý obsah sloupce content pomocí php?
|
||
|
Časová prodleva: 3 dny
|
|||
| maycza Profil |
#2 · Zasláno: 26. 3. 2015, 12:47:07
Kdyby to náhodou někdy někdo řešil, tak doporučuju tento odkaz. Je sice starší, ale mě to pomohlo. Jen jsem musel změnit typ sloupce
content z varbinary(max) na image.
Nahrávání souborů zůstalo jak je, pro stažení souboru jsem si upravil kód z článku (komentáře jsou původní): if (isset($_GET["file"])){$id_priloha=$_GET["file"];}
$dbconnect = odbc_connect('Driver=TDS;Server=servername;', 'user', 'password');
if($dbconnect === false) {echo "Chyba připojení k databázi";}
$data="";
$blok_dat=512; //data budeme z databáze číst po 512 b
if (isset($id_priloha) and is_numeric($id_priloha)){
$query="SELECT size, name, type FROM table_name.files WHERE id=".$id_priloha;
$soubory=ODBC_exec($dbconnect,$query);
while ($r=odbc_fetch_array($soubory)){
$velikost=$r["size"];
$jmeno=$r["name"];
$mime_type=$r["type"];
}
$p=0; //$p označuje pozici, odkud se začneme binárně soubor z databáze číst (pokud 0, tak od začátku)
//zjištění ukazatele a dalších pomocných proměnných
$sql="SELECT TEXTPTR(content) as textptr, DATALENGTH(content) as blobsize,
$p as chunkindex,
CASE WHEN $blok_dat< DATALENGTH(content) THEN 512 ELSE DATALENGTH(content) END as chunksize
FROM table_name.files WHERE id=".$id_priloha;
$rs=ODBC_exec($dbconnect,$sql);
while ($r=odbc_fetch_array($rs)){
//načtení výsledků z dtb do proměnných
$textptr=bin2hex($r["textptr"]); //ukazatel (musí být binární) na pozici souboru
$blobsize=$r["blobsize"]; //definuje celou velikost souboru
$chunksize=$r["chunksize"]; //definuje po kolika bitech se bude načítat soubor
//Soubor je nutné načítat po blocích! Nelze najednou… chunksize je velkost bloku
$chunkindex=$r["chunkindex"]; //def. pozici, odkud se začíná číst blok dat (jehož velikost def. $chunksize
}
//=================
if ($textptr<>""){ //jestliže je nalezen ukazatel
while (($chunkindex<$blobsize)){ //tento cyklus postupně načte všechna data
if (($chunkindex+$chunksize)>$blobsize){
/*
kdybychom chtěli načíst větší blok, než jaký můžeme => pak je nutné vzít jako blok přesnou velikost toto typicky nastane tehdy, je-li max. možná délka načítaných dat menší, než udává proměnná $blok_dat
*/
$chunksize=$blobsize-$chunkindex;
}
//celý princip je o tom, že SQL server není schopen vrátit víc jak 2048bitů.
//Proto tedy /po námi stanoveném kroku v proměnné proměnná $blok_dat (512b)/
//čteme celý soubor část po části a následně tyto bloky spojujeme do celku
$sql2="set textsize 512 READTEXT table_name.files.content 0x".$textptr." $chunkindex ".($chunksize-$p)."";
//nezapomeňme, že proměnná $p označuje počáteční pozici čtení dat;
$rs2=ODBC_exec($dbconnect,$sql2);
//přilepení bloku dat ke stávajícím
while ($r=odbc_fetch_array($rs2)){
$data.=$r["content"];
}
//navýšení indexu =>abychom četli následující blok dat
$chunkindex=$chunkindex+$chunksize;
}
}
//a máme načtená data
//odešleme HTTP hlavičku
header("Pragma: public"); //vypnutí cache pro proxy servery atp. pro HTTPverze 1.0
header("Expires: 0"); //datum expirace – nastavení na ihned
header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); //opět vypnutí cache; pro HTTP verze 1.1
header("Content-Description: File Transfer");
header("Content-Type: $mime_type");
header("Content-Length: " . $velikost);
header("Content-Disposition: attachment; filename=" . $jmeno);
// a nyní odešleme data prohlížeči
echo base64_decode($data);
exit();
} |
||
|
Časová prodleva: 11 let
|
|||
0