I am uploading files to a MySql DB through PHP.
I am able to upload files upto 1MB size (found out by trial and error).
Files greater than 1 MB in size are not getting uploaded.
The MySql error printed by mysql_error() function in PHP is:
MySQL server has gone away
Can anybody please help me with this?
The MySql server is up and running only for requests > 1MB it is giving this error.
Regards,
Mayank.
P.S.:
I am using a form to upload the file.
<FORM METHOD="post" ACTION="fileUpload.php" ENCTYPE="multipart/form-data">
<INPUT TYPE="hidden" NAME="MAX_FILE_SIZE" VALUE="300000000">
<INPUT TYPE="hidden" NAME="action" VALUE="upload">
Description: <TEXTAREA NAME="txtDescription" ROWS="1" COLS="80"></TEXTAREA>
<INPUT TYPE="file" NAME="binFile" ID="binFile">
<INPUT TYPE="submit" NAME="Upload" VALUE="Upload">
</FORM>
Your sql query probably exceeds the max_allowed_packet size in which case the server will disconnect.
You might be interested in mysqli_stmt::send_long_data which allows you to send parameters longer than max_allowed_packet in chunks.
Update: "How can i change it? Is using mysqli is the only option?"
Afaik the value can't be altered on a per-session base, i.e. if you cannot change the server configuration (my.cnf or startup parameters) the value will be read-only. edit: As the comment suggests you can change the global value of the mysql server after it has been started if you have the proper permissions.
PDO/PDO_MYSQL (as of phpversion 5.3.0) doesn't seem to support send_long_data, but I'm not sure about that either. That would leave mysqli as the only option. I've recently noticed that Wez Furlong joined stack overflow. Since he is one of the authors of the PDO implementation he might know (though he did not write the pdo_mysql module).
(Completely untested and ugly) example
// $mysqli = new mysqli(....
$fp = fopen($_FILES['binFile']['tmp_name'], 'rb') or die('!fopen');
//$result = $mysqli->query('SELECT ##max_allowed_packet') or die($mysqli->error);
//$chunkSize = $result->fetch_all();
//$chunkSize = $maxsize[0][0];
$chunkSize = 262144; // 256k chunks
$stmt = $mysqli->prepare('INSERT INTO foo (desc, bindata) VALUES (?,?)') or die($mysqli->error);
// silently truncate the description to 8k
$desc = 8192 < strlen($_POST['txtDescription']) ? $_POST['txtDescription'] : substr($_POST['txtDescription'], 0, 8192);
$stmt->bind_param('sb', $desc, null);
while(!feof($fp)) {
$chunk = fread($fp, $chunkSize);
$stmt->send_long_data(1, $chunk) or die('!send_long_data.'.$stmt->error);
}
$result = $stmt->execute();
In order to upload large files to your server with PHP, you need to change 2 parameters in your php.ini file.
; Maximum allowed size for uploaded files.
upload_max_filesize = 50M
; Maximum size of POST data that PHP will accept.
post_max_size = 50M
50M = 50Mb
Related
I'm trying to make file upload to server by form:
<form action="send_valid.php" method="POST" enctype= "multipart/form-data">
<br>
<input type="file" name="pdf" id="pdf" accept="application/pdf"/>
<input type="hidden" name="MAX_FILE_SIZE" value="10000000"/>
<input type="submit" value="WyĆlij">
</form>
and I want to allow user to send only pdf files of a max size 10Mb.
My php configuration for uploads is:
file_uploads = On
upload_tmp_dir = "E:\Xampp\tmp"
upload_max_filesize = 11M
max_file_uploads = 20
post_max_size = 12M
To check file size I use:
if($_SERVER["REQUEST_METHOD"] == "POST"){
var_dump($_FILES);
if(extract($_FILES)){
if($pdf['size']>10000000){
echo "File size is too large!";
}
}
Now I want to show user an error (for now) with echo when file is too big. It works fine if it is lower than 10Mb (even the code above works when I change size to 1Mb and file is larger then it will display echo), but for files of 10Mb and above it produces that error:
Warning: POST Content-Length of 11450416 bytes exceeds the limit of 8388608 bytes in Unknown on line 0
array(0) { }
I don't have any clue why it shows it exceeds 8Mb since in configs I couldn't find 8Mb anywhere.
Where can be the problem? Is there a way to catch an upload that exceeds configuration setting to not show user the php server error?
And if I want to make file validation does above method and checking file extension with for examle:
$ext = pathinfo($_POST['pdf'], PATHINFO_EXTENSION);
is it enough? Any insight on file validation would be really helpful.
Probably this
ini_set('post_max_size', '512M');
ini_set('upload_max_filesize', '512M');
Change 512 to any of you want.
Update the values of post_max_size and upload_max_filesize in your php configuration file.
Note that the values are measured in bytes.
Reference
http://php.net/manual/en/ini.core.php#ini.post-max-size
http://php.net/manual/en/ini.core.php#ini.upload-max-filesize
Put this code before move_uploaded_file function
if($_FILES['pdf']['size']>10000000) {
exit("File size is too large!");
}
Thanks
I am a PHP beginner and I am trying to upload PDF to my MySQL database. I tried adding some code to make it pdf compatible but it didn't work so i removed it and I have the PHP script that can upload .txt, word docs, images, etc but not PDF. What do you you suggest I should add to it so it works for PDF. Here's my script.
<html>
<head></head>
<body>
<form method="post" enctype="multipart/form-data">
<table width="350" border="0" cellpadding="1"
cellspacing="1" class="box">
<tr>
<td>Select a file to upload</td>
</tr>
<tr>
<td>
<input type="hidden" name="MAX_FILE_SIZE"
value="16000000">
<input name="userfile" type="file" id="userfile">
</td>
</tr>
<tr>
<td width="80"><input name="upload"
type="submit" class="box" id="upload" value=" Upload "></td>
</tr>
</table>
</form>
</body>
</html>
<?php
if(isset($_POST['upload']) && $_FILES['userfile']['size'] > 0)
{
$fileName = $_FILES['userfile']['name'];
$tmpName = $_FILES['userfile']['tmp_name'];
$fileSize = $_FILES['userfile']['size'];
$fileType = $_FILES['userfile']['type'];
$fileType=(get_magic_quotes_gpc()==0 ? mysql_real_escape_string(
$_FILES['userfile']['type']) : mysql_real_escape_string(
stripslashes ($_FILES['userfile'])));
$fp = fopen($tmpName, 'r');
$content = fread($fp, filesize($tmpName));
$content = addslashes($content);
fclose($fp);
if(!get_magic_quotes_gpc())
{
$fileName = addslashes($fileName);
}
$con = mysql_connect('localhost', 'root', '') or die(mysql_error());
$db = mysql_select_db('test', $con);
if($db){
$query = "INSERT INTO upload (name, size, type, content ) ".
"VALUES ('$fileName', '$fileSize', '$fileType', '$content')";
mysql_query($query) or die('Error, query failed');
mysql_close();
echo "<br>File $fileName uploaded<br>";
}else { echo "file upload failed"; }
}
?>
You should store this as binary data. So a column type of BLOB (or MEDIUMBLOB etc., depending on how large the files are - and how much a user can upload). With that, it shouldn't be a problem to store virtually any type of file content.
Furthermore, I don't think you should be adding slashes to the content and directly insert the values in a query, instead consider using parameters. Read up on PHP Data Objects (PDO: http://php.net/manual/en/book.pdo.php) which is a very nice and safe (if used properly!) extension for interacting with a database.
Magic quotes have been deprecated for a long time. You shouldn't use it anymore. Since PHP 5.4 it is removed from the language. Especially, when writing new scripts you should avoid this abandoned feature.
If your file is to big to be processed using a PHP file upload script, you might be interested in changing settings like post_max_size. See this thread for more details: Increasing the maximum post size
Instead of the general-use text manipulating function addslashes you should use the escaping function matching your database system. In this case it is mysqli_real_escape_string.
As PDF files contain binary data and no text, you shouldn't add and remove slashes on saving and after reading (text processing). Just escape the binary content blob using the adequate MySQL function when inserting the data into the database.
A suitable column type for entire files is MEDIUMBLOB. It allows a data length of up to ~16 MB.
After having talked about the php side, a few more hints concerning MySQL. MySQL limits the length of data packets being sent to it. If you use a shared hosting platform (and no dedicated server), chances are high of being limited to only 1 MB. The relevant configuration option is max_allowed_packet. This setting will limit the ability to store documents in the database. See this thread for ideas on how to resolve this problem.
In my opinion it's a bad idea in most cases to store entire documents into a relational database. I usually put the file meta data (size, filename, MIME type, ...) into a database table and store the uploaded binary data in a normal file system directory that isn't readable to the public (e.g. /srv/uploads). Then your files can become as big as you want without sacrificing your database's performance.
I'm making a web-based system using html and php, one of the functions is to allow students to upload files to the database, 3 files actually.
I made an input field of type file and I'm sure my PHP is correct but sometimes a warning I don't understand appears and the query doesn't work. but this does not always happen.. usually not..
Here's one of the fields in the HTML:
<tr><td> <p><span>C.V: </span> </td><td> <input class="contact" type="file" id ="CV" name="CV" value="" required /></p> </td></tr>
and here's the PHP
//check for CV
if ($_FILES["CV"]["size"] > 0)
{
$fileName = $_FILES['CV']['name'];
$tmpName = $_FILES['CV']['tmp_name'];
$fileSize = $_FILES['CV']['size'];
$fileType = $_FILES['CV']['type'];
//check if larger than 1M
if($fileSize > 1048576) {echo "<p style='color: red;'> Cannot upload <b>CV</b> due to large size. File must be less than 1MB </br> </p>"; $complete= false;}
//check if .PDF ( I need it to be PDF always)
else if($fileType != "application/pdf")
{
echo "<p style='color: red;'> Cannot upload <b>CV</b> file type must be a .PDF only </br> </p>"; $complete= false;}
//everything is fine:
else{
$fp = fopen($tmpName, 'r');
$CV = fread($fp, filesize($tmpName));
$CV = addslashes($CV);
fclose($fp);
if(!get_magic_quotes_gpc())
{
$fileName = addslashes($fileName);
}
echo "<br>CV: File $fileName uploaded with type $fileType and size $fileSize <br>";
}
}
SQL Query:
$qry=" UPDATE student SET CV = '$CV', Transcript='$tran',IELTScertificate='$EC', Status ='$stat' WHERE KSUID ='$KSUID'";
Warnings:
Warning:mysql_query(): MySQL server has gone away...line 330
Warning:mysql_query(): Error reading result set's header...line 330
330. $result=mysql_query($qry);
In the database I didn't use a table for uploaded files, I only need content but I don't care about the type because it'll always be a pdf, and I don't care about the name as long as it's stored in the right column.
I'm not sure if this is the problem? but I don't think so cause some files were successfully uploaded where other files with different size didn't.
Another issue I'm facing with retrieving the files..
when I download the file I get it correctly as a .pdf file but when I open it it says the file got damaged.. I'm not sure why? maybe because I'm using local server? though I don't think so but I'm tired trying to figure out :( if anybody faced such a problem before or if you know how to fix this problem please help me
HTML :
<a href='updatestudentlist.php?id=".$ksuid."&file=00'>CV</a> <br/>
PHP:
if(isset($_GET['file'])){
$file=intval($_GET['file']);
if($file==00) //I use this cause other files got different numbers
{
$query = "SELECT CV FROM student WHERE KSUID='".$_GET['id']."'";
$result = mysql_query($query) or die('Error, query failed');
list($content) = mysql_fetch_array($result);
header("Content-type: application/pdf");
header("Content-Disposition: attachment; filename=".$_GET['id']."_CV");
echo $content;
exit;
}
}
There are multiple issues at play here, mostly centered around how you're working with the database.
1) You shouldn't be using mysql_query() to interface with your database, because that module has been depreciated in favor of better, more current libraries (such as MySQLi). In particular, one major feature the MySQL extension lacks that MySQLi has is prepared statements, which is indirectly why you're getting the warning about the server going away.
Aside from opening yourself to injection attacks with your current code, it also produces an extremely large SQL query (because you're including the PDF itself inside the query string to update the student profile). If an individual query is taking too long to execute, the connection to the server will be dropped (which issues that particular warning). Thus, you should be getting the error from uploading larger PDFs, whereas smaller PDFs upload just fine.
If instead you use prepared statements, as available in the MySQLi extension, the server will be able to handle the extremely short query and then wait on the parameters to be passed as well, of which the extremely large PDF file-string will be one.
2) Your file is considered "damaged" because you're using addslashes() on it before inserting it into the database, but not using stripslashes() when you pull it out. Thus, the PDF you're serving up has most of the data right, but it has a bunch of extra slashes in it, which throws off the PDF reader.
The first part of question is mostly related to connectivity issues with the MySQL Server. There are a host of reasons that could happen. Check this link Server has gone away for the different reasons
I'm reading this line in Linux. However, when I'm echoing this in the browser, nothing shows up. Is there something wrong with how I used the echo line?
// relevant code snippets
$mypic = $_FILES['upload']['name'];
$temp = $_FILES['upload']['tmp_name'];
$type = $_FILES['upload']['type'];
/*$finfo=finfo_open(FILEINFO_MIME_TYPE);
$type=finfo_file($finfo,$temp);
finfo_close($finfo);*/
echo "<pre>"; print_r($_FILES);
echo $mypic."<br />";
echo $type."<br />";
echo $_FILES['upload']['error']."<br />";
echo var_dump($type)."<br />";
If you suspect something is wrong with how I'm handling file inputs in another file, I've included that php file in this link.
<form ENCTYPE="multipart/form-data" method="post" action="insert.php">
Name: <input type="text" name="name" maxlength="15" /><br />
Email: <input type="text" name="email" maxlength="30" /><br />
Password: <input type="password" name="password" maxlength="15" /><br />
Confirm Password: <input type="password" name="cpassword" maxlength="15" /><br />
<input type="hidden" name="MAX_FILE_SIZE" value="10000">
Choose your picture: <input type="file" name="upload"><p>
<input type="submit" name="submit" value="Register" /><br />
<p>
<center><h3><?php include("links.php"); ?></h3></center>
</form>
Here is the printout that I'm seeing:
Array (
[upload] => Array
(
[name] => protest.jpg
[type] =>
[tmp_name] =>
[error] => 2
[size] => 0
)
) protest.jpg
2 string(0) ""
------------------Update as of 9:40 p.m. May 5, 2012-------------------------
I tried an icon and found no problems other than permissions settings (I think I can solve this on my own for the time being). However, I'm still stuck on setting the file size. I followed Peter Stuart's instructions and got the following printout:
Apparently, the file size limits in these two settings are more than enough to handle the original images I had (which are under 200 kb). I don't know what more I can do in this case.
The file type is empty for the same reason that the filesize is 0 and the error is 2.
From Error Messages Explained:
UPLOAD_ERR_FORM_SIZE Value: 2; The uploaded file exceeds the
MAX_FILE_SIZE directive that was specified in the HTML form.
You have your max size set to 10000, which is in bytes, so that's roughly 10Kb. If it's a photo taken on any modern digital cam (over 4mgpx) it will probably need to be at least ten times that size. Just leave out the max size for now until you get a rough average of the image size people are submitting. PHP has a max upload size of its own to avoid tying up the line for too long.
To avoid issues like this in the future (not knowing if the file upload was successul), you probably want to wrap your code in something like:
$upload_error[0] = "AOK";
$upload_error[1] = "Server says: File too big!";
$upload_error[2] = "Browser says: File too big!";
$upload_error[3] = "File upload didn't finish.";
$upload_error[4] = "Ummm.... You forgot the file.";
$upload_error[6] = "Oops. Webmaster needs to fix something.";
$upload_error[7] = "Server says: I'm stuffed. Email webmaster.";
$upload_error[8] = "Server says: Not gonna do it. Webmaster needs to fix something.";
if($_FILES['upload']['error'] == 0) {
//do your thing and move it to the database.
} else {
$error_num = $_FILES['upload']['error'];
echo $upload_error[$error_num];
}
I would check your PHP upload size limit in your PHP ini file. It can cause adverse problems :)
If you create or go into your php.ini file and make sure the settings are as follows:
upload_max_filesize = 5M
post_max_size = 5M
The order of settings are also matter, and it should be like
upload_max_filesize = 5M
post_max_size = 5M
And I always got maximum size error when post_max_size place before upload_max_filesize.
This problem has 7 years but I stopped with it without finding a clear procedure to understand it. This is How I controlled it:
The sintom was that I could upload SMALL images (less than 2MB) BUT not bigger than 2MB. It's important to identify perfectly the ERROR. In this case "UPLOAD_ERR_FORM_SIZE:" The sintom in the DEBUG was that $_FILES["image"]["type"] = "", (ridiculous) and I knew that was a .JPG image for sure.
SOLUTION: Using XAMPP, STOP it. Configure php.ini, go to "upload_max_filesize=2M" which means that the file you try to upload has a limit of 2 Megabytes, So you Will change it to (for example) 3M. After that, I started again XAMPP, and proceeded to upload an image of 2.5 MB, and was successful.
Im sorry but my status can't show images of configuration in this comment.
I have an html input field, such as
<form method="post" action="process.php" enctype="multipart/form-data">
<div>
<h3>Files:</h3>
<input type="file" multiple="multiple" name="image[]" />
<input type="submit" value="Upload Image" />
</div>
</form>
And I want the user to be able to upload multiple files at once. My php for this uses a for loop to cycle through all the files, gathers information on each one, and then uploads them one by one.
for($i = 0;$image['name'][$i] == true;$i++)
{
//code
}
But this won't upload more than 20, ending with an error, Notice: Undefined offset: 20 in F:\www\hdp\process.php on line 39. Now, if I were to upload 5 images, it would give me Notice: Undefined offset: 5 in F:\www\hdp\process.php on line 39, but that would be ok because it would still upload all 5 photos (0,1,2,3,4). I need it to upload all the photos the user adds.
I know uploading lots of files at once could be a bad idea, but it is just the site admin, and it's a photography portfolio site. So he needs to be able to upload a lot of photos at once. And if it's important, they are being uploaded to a MySQL database.
max_file_uploads in php.ini setting was the cause. Change it to what you want and it will work.
I'm a bit confused by the 'wont upload more than 20' part... what are you basing this on? You're getting an error either way it seems.
Change your for loop to check for isset($image['name'][$i]) instead, and you will no longer get an error.
for($i = 0; isset($image['name'][$i]); $i++)
{
//code
}
As mentioned by yes123, you risk hitting the maximum POST size and should check php.ini.
Check your php.ini settings for post_max_size
Also
upload_max_filesize
memory_limit
max_execution_time
max_input_time
Similar to Fosco's solution, but works differently (uses sizeof and a int to int comparison instead of an isset)
Neither this nor his are necessarily any better, just different ways to tackle the problem.
for($i = 0, $size = sizeof($image['name']); $i < $size; $i++)
{
//code
}
And no, it doesn't run sizeof() each iteration. That's an easy way to screw over performance.