diff --git a/include/class.file.php b/include/class.file.php index 4873ffb4528d8dadf99c1dace26044651ffbadde..36f013a6a0e78fedb302a37a1897b41e004a7755 100644 --- a/include/class.file.php +++ b/include/class.file.php @@ -92,16 +92,15 @@ class AttachmentFile { } function sendData() { - # XXX: For maximum efficiency, - # do "show variables like 'max_allowed_packet'", and use the - # lesser of half of PHP's memory limit and that value as the - # chunk_size $chunk_size = 256 * 1024; - for ($start=1; $start<$this->getSize(); $start+=$chunk_size) { + $start = 1; + for (;;) { list($data) = db_fetch_row(db_query( 'SELECT SUBSTRING(filedata,'.$start.','.$chunk_size .') FROM '.FILE_TABLE.' WHERE id='.db_input($this->getId()))); + if (!$data) break; echo $data; + $start += $chunk_size; } } @@ -185,14 +184,27 @@ class AttachmentFile { if (!(db_query($sql) && ($id=db_insert_id()))) return false; - foreach (str_split($file['data'], 1024*100) as $chunk) { + $chunk_size = 256 * 1024; + $start = 0; + # This boils down to a disagreement between the MySQL community and + # developers. I'll refrain from a soapbox discussion here, but MySQL + # will truncate the field to '' when the length of a CONCAT expression + # exceeds the value of max_allowed_packet. See the following bugs for + # more information. The easiest fix is to expand the parameter. + # http://bugs.mysql.com/bug.php?id=22853 + # http://bugs.mysql.com/bug.php?id=34782 + # http://bugs.mysql.com/bug.php?id=63919 + if (db_get_variable('max_allowed_packet') < strlen($file['data'])) + db_set_variable('max_allowed_packet', strlen($file['data']) + $chunk_size); + while ($chunk = substr($file['data'], $start, $chunk_size)) { $sql='UPDATE '.FILE_TABLE - .' SET filedata = CONCAT(filedata,'.db_input($chunk).')' + .' SET filedata = CONCAT(filedata, 0x'.bin2hex($chunk).')' .' WHERE id='.db_input($id); if(!db_query($sql)) { db_query('DELETE FROM '.FILE_TABLE.' WHERE id='.db_input($id).' LIMIT 1'); return false; } + $start += $chunk_size; } return $id;