note 31032 deleted from features.file-upload by sniper
| From: | sniper@php.net | Date: | Thu, 29 Jan 2004 07:52:58 +0000 |
| Subject: | note 31032 deleted from features.file-upload by sniper | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-64352@lists.php.net to get a copy of this message | ||
Note Submitter: mightye@mightye.org
----
On Handling uploads of large files on Windows and/or storing in MySQL.
I see a couple of people suggest you do this:
$data = addslashes(fread(fopen($file['tmp_name'], "r"),
($file['size'])));
First, on Windows, you want "r" to be "rb" because the file may be binary.
Second, if this is a large file, this is a highly inefficient script. Plus if you are storing the
file in MySQL, with a large file, your query will more than likely exceed the MySQL default max
size, and you will get the "MySQL has gone away" error.
What I suggest is that you handle a file in parts, with a table for the file name, mime type, file
size, etc, and a separate table to hold the actual file data. Then do something like this:
define("MAX_SQL",50000);
$fp = fopen($file['tmp_name'],"rb");//
$sql = "INSERT INTO files (
filename,mimetype,filesize)
VALUES
('$file[name]', '$file[type]','$file[size]')";
mysql_query($sql) or die(mysql_error(LINK));
$id = mysql_insert_id();
while (!feof($fp)){
$data = addslashes(fread($fp,MAX_SQL));
$sql = "INSERT INTO filedata (fileid,filedata)
VALUES($id,\"".$data."\")";
mysql_query($sql) or die(mysql_error(LINK));
}
You will want an auto incrementing field in filedata as you will need to order by this
field to ensure that the file is reassembled in the correct order, or else add an incrementing ID in
your script.
This model is many orders of magnitude more efficient than attempting to load an entire large upload
in to memory all at once, and generating a huge SQL statement. The "b" switch ensures
that in Windows we don't hit a premature end of file, and the fact that we are only loading
portions of the file in to memory at a time, and are passing only portions of it to the database at
a time represents a significantly lower load on the server both processor wise and memory wise.
In my testing, this later model required 5 seconds of processing time for a 100 meg file after the
upload was complete, while other models timed out at my 120 second threshold before the file was
completely loaded in to memory.