[php] file upload naar blob probleem

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik probeer via de browser bestanden (pdfjes) te uploaden naar een mysql database. De data sla ik op in een mediumblobje. Dat gaat allemaal goed tot ik een bestand met een bestandsgrootte boven ongeveer 900 KB kies. Ook als ik handmatig in phpmyadmin probeer een record aan te maken met een file groter dan ca. 900KB gaat t mis. Hoe kan dit? Het lijkt mij dat het een server probleem is. Restrictie oid. Ik kan overigens de file wel uploaden naar een dir op de server via het script. Alleen het overzetten naar de db is een probleem.

Onderstaand scriptje heb ik er voor geschreven:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$query_pdf = "INSERT INTO pdf (titel, schrijvers, datum_geschreven, datum_upload, pdf, sleutelwaarde, tekst, filesize, filetype) VALUES ('$titel','$schrijvers','$datum_geschreven','$datum_upload','$pdf_bestand','$sleutel','$inhoud_escaped','$pdf_size','$pdf_type')";
$result_pdf = mysql_query($query_pdf);
$pdfid = mysql_insert_id();

$geopende_file = fopen("files/temp/" . $pdf_bestand, "r");

   do
   {
      $gelezen = fread($geopende_file, 4096);
      
      if (strlen($gelezen) == 0)
      {
       break;
      }
      
      $blob_data = addslashes($gelezen);

      $query = "UPDATE pdf SET file=CONCAT(file,'$blob_data') WHERE id = '$pdfid'";
      mysql_query($query) or die("Bestand kan niet toegevoegd worden aan database.");

      ob_flush();
   }
   while(true);

Waarom [table]-tags als er ook [code]- en [php]-tags zijn? ;)

[ Voor 12% gewijzigd door NMe op 13-11-2005 02:20 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Ligt aan je apache of php cfg, die moet je ff nakijken.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Waarom update je elke keer in die loop? Je realiseert je dat je nu telkens stukjes van 4KB aan het wegschrijven bent naar je database, en je dus een kleine 200 queries hebt voor een relatief kleine file van 800KB?

Probeer het eens zo:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$geopende_file = fopen("files/temp/" . $pdf_bestand, "rb");

$gelezen = fread($geopende_file, 4096);
$data = '';

while (!empty($gelezen))
{
      $data .= addslashes($gelezen);
      $gelezen = fread($geopende_file, 4096);
}
fclose($geopende_file);

$query_pdf = "INSERT INTO pdf (titel, schrijvers, datum_geschreven, datum_upload, pdf, sleutelwaarde, tekst, filesize, filetype, file) VALUES ('$titel','$schrijvers','$datum_geschreven','$datum_upload','$pdf_bestand','$sleutel','$inhoud_escaped','$pdf_size','$pdf_type', '$data')";
$result_pdf = mysql_query($query_pdf);


Of nog makkelijker:
PHP:
1
2
3
4
$data = file_get_contents("files/temp/" . $pdf_bestand);

$query_pdf = "INSERT INTO pdf (titel, schrijvers, datum_geschreven, datum_upload, pdf, sleutelwaarde, tekst, filesize, filetype, file) VALUES ('$titel','$schrijvers','$datum_geschreven','$datum_upload','$pdf_bestand','$sleutel','$inhoud_escaped','$pdf_size','$pdf_type', '$data')";
$result_pdf = mysql_query($query_pdf);

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Noork
  • Registratie: Juni 2001
  • Niet online
Waarom stop je de bestanden eigenlijk in een database? Je database wordt hier erg groot en traag van. Het is veel effectiever om de bestanden gewoon in het filesystem op te slaan en verwijzingen hiervan in de db op te nemen.

Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 18-09 16:28

Bosmonster

*zucht*

Dit heeft te maken met de maximale query lengte van MySQL, daar moet je ook nog even wat instellen.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 21:01
Er zijn in zo'n geval drie limieten:
[list=1]
• de maximale grootte van een geüpload bestand die PHP toestaat;
• de maximale grootte van een query die je naar de MySQL engine kunt versturen;
• de maximale grootte van de data die je in een mediumblob kwijt kunt.

Meestal loop je eerst tegen limiet 1 aan; die is standaard 2 MB maar misschien is het in jouw geval 1 MB. Je kunt die wijzigen in php.ini.

Limiet 2 ontwijk je mooi door steeds stukjes van 4 KB toe te voegen. Het is misschien wat traag, maar je voorkomt daarmee dat je queries groter worden dan ~10KB. De standaard limiet voor queries is (geloof ik) 16 MB dus daar zou het hier ook niet aan moeten liggen. Je kunt dit instellen als max_packet_size in my.cnf (maar de feitelijke limiet is gelijk aan het minimum van de max_packet _size van zowel de client als de server).

Limiet 3 kun je zelf kiezen; in een MEDIUMBLOB past standaard 16 MB maar misschien heb je 'm kleiner gedefinieerd bij het maken van de tabel.

Omdat je zelf nog niets gedebugged hebt is het lastig aan te geven wat er mis gaat, maar mijn gok is de uploaded data size van PHP. Hou wel ook rekening met de andere twee limieten als je nog grotere bestanden (zeg, boven de 10MB) wil uploaden.

edit:
Overigens is de meest efficiënte manier om een lokaal bestand in te lezen met de LOAD_FILE() constructie:
SQL:
1
UPDATE tbl_name SET blob_column=LOAD_FILE('/tmp/picture') WHERE id=1;

Dat omzeilt het hele punt 2 en voorkomt dat je het hele bestand in het geheugen moet laden en moet escapen (wat flink kostbaar is). Voor echt grote bestanden is dat i.m.o. de enige way to go (tenzij je tegenwoordig geparametriseerde queries kunt schrijven in PHP). Helaas werkt het alleen als je databaseserver op de lokale webserver draait en moet je het bestand readable maken voor MySQL (wat vanuit security-oogpunt misschien niet ideaal is).

[ Voor 22% gewijzigd door Soultaker op 13-11-2005 16:51 ]


Verwijderd

Topicstarter
yo mensen,
thnx voor de tips

probleem zit m in een maximale upload betreffende blobs. universiteits server die ik gebruik heeft dat deel lichtelijk dichtgetimmerd, dus nu maar vriendelijk verzoeken of ze een uitzondering willen maken. en zo niet, dan bedenk ik wel weer wat...

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 18-09 16:28

Bosmonster

*zucht*

Soultaker schreef op zondag 13 november 2005 @ 16:45:

Limiet 2 ontwijk je mooi door steeds stukjes van 4 KB toe te voegen. Het is misschien wat traag, maar je voorkomt daarmee dat je queries groter worden dan ~10KB. De standaard limiet voor queries is (geloof ik) 16 MB dus daar zou het hier ook niet aan moeten liggen. Je kunt dit instellen als max_packet_size in my.cnf (maar de feitelijke limiet is gelijk aan het minimum van de max_packet _size van zowel de client als de server).
De standaard packet size voor MySQL is dus 1MB en dat zal dus het eerste zijn waar die tegenaan loopt, aangezien de standaard limieten van PHP op 2MB liggen.

Om je inserts in stukjes van 4KB te gaan hakken lijkt me niet zo'n goed plan.. voor een beetje bestand ben je dan honderden, zo niet duizenden query's verder.. Neem dan wat grotere chunks (als je query's van 1MB kunt versturen, neem dan 900K ofzo als chunk size). Weinig reden kleiner te nemen.

[ Voor 8% gewijzigd door Bosmonster op 17-11-2005 17:14 ]

Pagina: 1