I can't upload pdf to my mysql database - php

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.

Related

How can I compress blob image when retrieving to database?

Im using the following code to upload the image in my database:
<form>
<input type="file" name="image">
<input type="submit name="upload">
</form>
<?php
$mysqli=new mysqli("localhost","root","","mydb");
if (isset($_POST['upload'])) {
$photo = addslashes(file_get_contents($_FILES["image"]["tmp_name"]));
$result=$mysqli->query("INSERT INTO images_tbl(image) VALUES('$photo')");
?>
and retrieve the photo this way:
<?php
$result=$mysqli->query("SELECT image FROM image_tbl");
while ($test=mysqli_fetch_array($result)) {
$getphoto = $test['image'];
}
echo'<img src="data:image/jpeg;base64,'.base64_encode($getphoto).'" style="width: 40px; 40px;" class="w3-round" draggable="false" /> ';
?>
When I upload a large image it loads the original file size. I want to optimize my website. Is there any way to compress the image when I retrieve them to the database so it loads faster to the website?
I would suggest not adding images to the database. At least not a MySQL database.
Instead, try to store images in the filesystem and only store the filesystem path in the database.
Consider renaming the files to long unique random names and storing that along with the original filename in the database.
Using PHP you can serve your files using their original names:
header('Content-Type: image/jpeg');
header('Content-disposition: attachment; filename="'.$filenameOriginal."\n");
readfile($filenameStorage);
MySQL is great att manipulating text, large blobs of binary data are a different story though. You should also ask yourself what you are gaining by storing images in the database.
About compression. Images are commonly compressed quite well so further compressing them for database storage is usually not feasible.
I would also strongly urge you to look into Prepared Statements for MySQL.
https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
That allows you to use queries like:
INSERT INTO images_tbl(image) VALUES(?)
The question mark signifies a variable which you pass to MySQL as binary with a separate function. This prevents SQL injection attacks which addslashes() definitely will not.
https://www.php.net/manual/en/mysqli-stmt.bind-param.php

Why is my image uploaded using PHP not being stored correctly in a longblob

I am having issues storing a .JPG image in my MySQL database. I am using the PHP code below to store it into the database (in long blob form). My code appears to be completely error free and every thing seems to act as it should aside from the fact that the image is only stored in what appears to be 36 B size on PHPMyAdmin.
I would expect the image to be much larger (22 MB supposedly).
<?php
require '../FirstWebsite/CommonFunctions.php';
DB_Connect();
$dblink = DB_Connect();
?>
<html>
<body>
<form method="post" enctype="multipart/form-data">
<br/>
<input type="file" name="selectImage">
<br/>
<input type="submit" name="submitImage" value="submit">
</form>
<?php
if(isset($_POST['submitImage'])){
if(getimagesize($_FILES['selectImage']['tmp_name'])==FALSE){
echo 'please select an actual image';
}
else{
$getImage = mysqli_real_escape_string($dblink, $_FILES['selectImage']['tmp_name']);
$name = mysqli_real_escape_string($dblink, $_FILES['selectImage']['name']);
$image = base64_encode($getImage);
saveImage($name, $image, $dblink);
}
}
function saveImage($name, $image, $dblink){
$query = "INSERT INTO trialtable2 (caption, actualpicture) VALUES ('$name','$image')";
$queryCheck = mysqli_query($dblink, $query);
if($queryCheck == TRUE){
echo '<br/> uploaded';
}
else{
echo '<br/> not uploaded';
}
}
?>
</body>
</html>
what I have done
attempted uploading .jpeg .JPG .jpg (same but still...) .tif .png
file_upload = on (or whatever) is already on in php.ini
it is a long blob type in the data base table
Supposedly storing images in a database is no the way to go however this is what I am working with for the time being.
versions
wamp: 2.5
apache: 2.4.9
mysql: 5.6.17
php: 5.5.12
I believe that this question is not a replica as I haven't been able to find an answer elsewhere. If I am doing something incorrectly feel free to let me know as I am still new to the community.
tmp_name is the temporary path to the file, this is why you're only seeing a few bytes.
Remove any escaping (including addslashes).
use file_get_contents($_FILES['selectImage']['tmp_name']) to get the actual contents of the image for inserting into your database.
It generally isn't a great idea to store the blobs in the database, and better to store the path (like you're currently doing). If you choose to go the path route, you need to use something like move_uploaded_file to move the file to a persistent location.

PHP: Uploading, downloading .pdf file without using table for uploaded files and the files get damage.

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

Uploaded images to mysql database, but can I retrieve it for an edit page?

$fileName = $_FILES['userfile']['name'];
$tmpName = $_FILES['userfile']['tmp_name'];
$fileSize = $_FILES['userfile']['size'];
$fileType = $_FILES['userfile']['type'];
$fp = fopen($tmpName, 'r');
$content = fread($fp, filesize($tmpName));
$content = addslashes($content);
fclose($fp);
if(!get_magic_quotes_gpc())
{
$fileName = addslashes($fileName);
}
$fileName_th = $_FILES['thumbnail']['name'];
$tmpName_th = $_FILES['thumbnail']['tmp_name'];
$fileSize_th = $_FILES['thumbnail']['size'];
$fileType_th = $_FILES['thumbnail']['type'];
$fp_th = fopen($tmpName_th, 'r');
$content_th = fread($fp_th, filesize($tmpName_th));
$content_th = addslashes($content_th);
fclose($fp_th);
if(!get_magic_quotes_gpc())
{
$fileName_th = addslashes($fileName_th);
}
$query = "INSERT INTO Images (profile_id, thumb, name, size, type, content ) ".
"VALUES ('$profile_id', 0, '$fileName', '$fileSize', '$fileType', '$content'),('$profile_id', 1, '$fileName_th', '$fileSize_th', '$fileType_th', '$content_th') ";
$r = mysqli_query($dbc, $query);
echo "<br>$first_name uploaded successfully";
That is the method im using to upload my images to my database. Now, what I want to do is to have an edit page which edits my form elements like text, along with making changes to the images.
I know how to query text elements and place them back into their respective input fields, but how do i do that for files like images?
Side question: What is the best way of "uploading" files to the database? Is it my way? Or is there a way of just writing files to a directory and saving the path in a database?
Good question. You can't in the same sense as text elements as potentially the image would not exist at the same location as you have stored if you are accessing the interface on a different computer.
When I've seen this kind of requirement in the past, the stored image is normally simply displayed and an option to replace/remove it is given. Unlike a text input, you're never going to change part of the image, you're going to change the whole thing so there's no need to provide the stored image path for editing.
Unless you have a specific need to store the file the way you are, one fairly straightforward solution would be to upload the files to a webserver (but not directly to the database) and simply store the link to them (this is what I've done for a podcasting solution, using mp3s rather than images, but much of the idea is the same). With the link, you could simply use <img> tags in your layout where the src field is populated from the information you dropped in your database.
You need to serve them to the client as an image type. Generally, I would implement a view (or page, depending on your terminology ;)) that is used to query for and render the image. For example: http://myurl.com/index.php/images/index/id/[db image pkey] (that is, if you're using an MVC framework such as CI, otherwise you can use any .php file to achieve the same result).
Using the example URL, the controller (images) would be responsible for instantiating an image model that queries the database for the image with the pkey specified in the URL. The view (or page) would take the data result from the model, simply set the Content-type header to whatever the image content type is, and then serve the binary image data to the client.
AFAIK, there's no way to achieve this inline when you're rendering the rest of your form data as it's a different MIME type.
Edit: Having said the above, after a little reading, it seems that you might not want to do this anyway (read this for further details as to why not). It would be better to store them as static images on the file system.
you need just add header like this image.php
<?php
if (!empty($_GET['image']) && $_GET['image'] > 0) {
//Connect to the database
mysql_connect("localhost","root","root");
mysql_select_db("database");
//Select image content
$sql = mysql_query("SELECT `content`, `type` FROM `Images` WHERE profile_id = ".(int)$_GET['image']." LIMIT 1");
$row = mysql_fetch_assoc($sql);
//Just display the image and finish the application
header("Content-type: image/{$row['type']}");
die($row['content']);
}
?>
There can be some bugs. The main thing is to send the proper headers.
To that image you can access with tag like this:
<img src="image.php?image=1" alt="" />
But if you want to display image in the same scene you need encode that to base64 and display inline like this:
//Imagine that we already got content from the database
$row['content'] = base64_encode($row['content']);
//Prepare inline image
$row['content'] = "data:image/{$row['type']};base64,".$row['content'];
//You will get something like this
/*
data:image/png;base64,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%3D
*/
echo "<img src=\"{$row['content']}\" />";

Upload size problem in PHP and MySql

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

Categories