PDO Blob Insert Missing Data - php

I'm utilizing phantom to capture images, then upload them to a centralized MySQL DB.
The issue that I'm running into is that it's consistently cutting the end off of every file I try and push. It doesn't matter if it's .pdf, .png, .docx, .xlsx... it's cutting off part of the file, thereby corrupting it. The weird thing is that it always cuts the same amount off each file.
My SQL insert code is:
$put_linkdata = $DBW->prepare('INSERT `'.$tableD.'` SET
captured = :capture_time,
error = :eYN,
link = :link,
image = :image,
html = :html,
`text` = :plaintext,
file = :file,
mimetype = :mimetype');
$put_linkdata->bindValue(':capture_time', date('Y-m-d H:i:s',$record['timestamp']));
$put_linkdata->bindValue(':link', $item['url']);
$put_linkdata->bindValue(':mimetype', $record['mimetype']);
$put_linkdata->bindParam(':eYN', $record['error'], PDO::PARAM_STR);
$put_linkdata->bindParam(':image', $record_child['image'], PDO::PARAM_LOB);
$put_linkdata->bindParam(':plaintext', $record_child['text'], PDO::PARAM_LOB);
$put_linkdata->bindParam(':html', $record_child['html'], PDO::PARAM_LOB);
$put_linkdata->bindParam(':file', $record_child['file'], PDO::PARAM_LOB);
if($put_linkdata->execute()){
$linkData_record['id'] = $DBW->lastInsertId();
print PHP_EOL.mb_strlen($record_child['image'], '8bit');
print PHP_EOL.PHP_EOL.'~~~~~~~~~~~~~~~~~~~~~~~~~~~'.PHP_EOL.PHP_EOL;
die();
}
else{
throw New Exception('Error inserting linkdata record into archive - SQL error "'.$put_linkdata->queryString.'"'.PHP_EOL.PHP_EOL.$put_linkdata->errorInfo());
}
I've run a ton of tests and everything prior to here the data still maintains integrity, and if I file_put_contents() it's identical to the captured image or file.
Example of images, pulling google.com gives me a 25K image, but the upload is 17.2K. A pdf that's 55K is uploading at 40.7K. Another pdf is 1.5 MB, but uploads at 1.1MB. When I diff the file against the db blob, the blob in the DB is missing content at the bottom of the file.
The size, and content isn't consistent across files, but IS consistent for identical captures.
Anyone have any ideas?
Update
I've narrowed it down to something happening between the prepared statement and the upload.
Also, this happens in both PDO and MySQLI when using a prepared statement. The first assumption was that the charset encoding somewhere is incorrect, however everything is defined as UTF8 (db, table, PDO connection, config files).

Finding out the issue, this post seems rather silly now, but incase anyone runs into this issue in the future...
There's an error with old versions of PHPMyAdmin where it doesn't correctly show or download data in blob columns.

Related

Saving file name as `BLOB` in database

While I'm sending file ( type="file") to database (PHPmyAdmin), instead of saving with file name it saves as BLOB as shown in the following figure.
I found the the similar question Saving Files as blob in database ajax php pdo
here but didn't help me. My php code is as follows for sending file to the database.
$info = pathinfo($_FILES['file']['name']);
$ext = $info['extension']; // get the extension of the file
$newname = $get.".".$ext; //$newname='newfilename.'.$ext
$target ="folder/".$newname;
$doc= move_uploaded_file( $_FILES['file']['tmp_name'], $target);
$sql="INSERT INTO apply(mobile,doc,position)
VALUES (' $mobile','$newname',' $position')";
$query=mysqli_query($conn, $sql);
The file is sending to target folder (named folder) with the correct required name but Why I'm not getting the same name in the database. What's going wrong in my code?
Thanks in advance.
First of all, you should not tore files into the database directly because of critical performance issues.
Suggested way is to store files in file system, and store their path in database as TEXT or Varchar.
Now coming to your question:
While I'm sending file ( type="file") to database (PHPmyAdmin), instead of saving with file name it saves as BLOB as shown in the following figure.
Every file is composed of binaries but in different order and format. Storing it in database is not actually tricky. Database converts them into array of bytes/ stream of bytes and then stores these byte format data into the table.
When a fetch query is fired, it returns the exact byte stream in response. And at application level, these bytes are treated as files by their respective encoding techniques.
It's worth reading this post and subsequent link in the accepted answer.

saving blob file in oracle using php

please tell me how can i insert pdf or doc files into oracle blob field .
this is the code which i use for varchr data type and this is fine but how can i save the files into blob data type please help me !!!
if(isset($_POST['elm1'])) {
$pdata=$_POST['elm1'];
$profile_name=$_POST['profilename'];
$profile_id=$_POST['profileid'];
$query = "insert into prepaid_profiles values('$profile_id' , '$profile_name','$pdata')";
$result = oci_parse($dbc,$query);
oci_execute($result);
oci_close($dbc);
When user uploads file, save it in server, show only link to it. When saved text from editor, you save only link (with rest of text). File is still on server.
But if you really need to make your database huge and slowly, read uploaded file with file_get_contents, that convert it to base64 and save to database long string (no idea why it's better).
TinyMCE don't need file content in <textarea>.

Unable to get JSON data from Img2Json API for large files in PHP

I am using http://img2json.appspot.com/ to retrieve and store the Exif data for user uploaded images. I noticed that for smaller files things work great. For larger files, or for files with a large amount of Exif data, the file is stored but the Exif data is not. I don't know if this is because the service is taking to long to produce the JSON, or if there is a memory issue since I'm storing all the JSON in a PHP array.
My code for retrieving the Exif data for a user uploaded image is as follows:
$exifd = file_get_contents("http://img2json.appspot.com/go/url=http://myURL.com/$fileName");
$response = json_decode($exifd, true);
$shut = $response['exif']['ShutterSpeedValue'];
$iso = $response['exif']['ISOSpeedRatings'];
$dateTime = $response['exif']['DateTime'];
$aperture = $response['exif']['ApertureValue'];
$focalLength = $response['exif']['FocalLength'];
$make = $response['exif']['Make'];
$model = $response['exif']['Model'];
$software = $response['exif']['Software'];
$flash = $response['exif']['Flash'];
$sql="INSERT INTO EXIF (uniqueID, dateTime, aperture, focalLength, make, model, software, shutterSpeed, ISO, flash)
VALUES('$id', '$dateTime', '$aperture', '$focalLength', '$make', '$model', '$software', '$shut', '$iso', '$flash')";
if (!mysql_query($sql,$link))
{
die('Error: ' . mysql_error());
}
}else{
echo "Something went wrong while uploading your file... sorry.";
}
As I mentioned before, this works great for the most part, but it doesn't work on large files (large in size or large in the amount of Exif data) and here and there a small file will fail as well.
Here is an image that works fine for me: http://img2json.appspot.com/go/?callback=hello&url=http://cloudousmain.s3.amazonaws.com/olympus-c960.jpg
Two that fail: http://img2json.appspot.com/go/?callback=hello&url=http://cloudousmain.s3.amazonaws.com/54img.JPG
and
http://img2json.appspot.com/go/?callback=hello&url=http://cloudousmain.s3.amazonaws.com/IMG_20130329_120227.jpg
I've increased the memory in the ini file with no success. Also, it might be worth noting that while images are being processed a progress bar is displayed until things are finished (or supposed to be finished). Any ideas?
Edit: switching to curl and using var_dump reveals that the images that "don't work" are dumping as NULL, while the ones that work fine give me an array of Exif data as expected.
Looks like it's an AWS error, which is written in XML and cannot be parsed for EXIF data. I'm getting "Access Denied" when I try to view the bad images in the browser, but the good one shows the image.
Fail: http://cloudousmain.s3.amazonaws.com/54img.JPG
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>2537951DEE216FEB</RequestId>
<HostId>Ep4//A7Oq+n/C3ilB5jyazx0Bs9fQfMRyNg+pX/rs+dkziFhJIkgHNWHc+CAZVgR</HostId>
</Error>
Pass: http://cloudousmain.s3.amazonaws.com/olympus-c960.jpg
To check for this in the code, ping the header for the image file and check if the content type is application/xml or if the http code is 403. I'd suggest either using http_head() or flagging CURLOPT_HEADER in curl_setopt() for this information.
I ended up defaulting to PHP's Exif functions when the JSON was NULL. Not what I wanted to do, but it worked.

Upload image and thumbnail via PHP

So I need a very simple script to resize an image and upload the thumbnail in PHP. Please don't recommend a library because I'd rather be able to edit and learn from it with ease.
I had written a small PHP script on my own to upload an image and name it after its ID in the database and intended to make the thumb as simple as adding "thumb" to the end of the name (such as 123thumb.jpg), but I sort of ruined it trying to work in thumbnails.
Here's what it somewhat looked like:
mysql_query('
INSERT INTO art (
artist,
title,
extension)
VALUES (
1,
"Penguins",
"'.end(explode('.',$_FILES['art']['name'])).'")') ;
move_uploaded_file($_FILES['art']['tmp_name'],'images/'.mysql_insert_id()..end(explode('.',$_FILES['art']['name']))
Bad bad design. 1. No error checking on the query and using raw user-provided data in the query, leading to a gaping sql injection vulnerability. 2. Using raw user-provided filenames to store the files in, even if it does have a database ID prepended. 3. Blindly assuming the insert query worked, such that msyql_insert_id might not return anything. 3. blindly assuming the move command works.
A better/safer methodology is:
if ($_FILES['art']['error'] !== UPLOAD_ERR_OK) {
die("Upload failed with error code " . $_FILES['art']['error']);
}
$filename = mysql_real_escape_string(basename($_FILES['art']['name']));
mysql_query("INSERT .... VALUES (1, 'Penguins', '$filename', ...)") or die(mysql_error());
move_uploaded_files(...) or die("Failed to move file");
There's more/better validation/error handling that can be done, but this is the skeleton of something far safer/more reliable than your version.
Besides all of the potential exploits of your script (see other answer) this page might be very helpful for teaching you how to resize the image to get a thumbnail. You will have to use a library like GD (built in to PHP) to resize the image.
http://salman-w.blogspot.com/2008/10/resize-images-using-phpgd-library.html
(Found it in another SO question.)
EDIT: And, of course, don't forget the PHP manual. http://php.net/manual/en/book.image.php

How to display an Image from a mysql blob

I am trying to display an image from a MySQL blob field. I have tried a few different things and none of them seem to work.
I have tried:
header("Content-type: $type"); img src = $blobData;
header("Content-type: $type"); echo($blobData);
<?php
header("Content-type: $type");
echo $blobData;
?>
This code looks perfectly OK. However, I heard a similar complain from another person and I was able to troubleshoot it by assuring that:
The php script does not output any extra character before or after sending the binary image data.
The php script is saved as a pure ASCII text file, not as a Unicode/UTF-8 encoded file. The Unicode/UTF-8 encoded PHP files might include a signature as the first bytes. These bytes will be invisible in your text editor but server will send these few extra bytes to the browser before the JPEG/GIF/PNG data. The browser will therefore find the wrong signature in the beginning of data. To workaround, create a blank text file in notepad, paste in the php code and save the file in ANSI encoding.
Another option you might consider (assuming you are on Apache):
Create an .htaccess file with a mod_rewrite for all image extensions (png, jpg, gif).
Have it redirect to a php script that looks up the image requested in the DB. If it is there, it echos out the header and BLOG. If it isn't there, it returns a standard 404.
This way you can have:
<img src="adorablepuppy.jpg" />
Which then gets redirected ala:
RewriteEngine on
RewriteRule \.(gif|jpg|png)$ imagelookup.php
This script does a query for the image, which (obviously) assumes that the requested image has a unique key that matches the filename in the URL:
$url = $_SERVER['REQUEST_URI'];
$url_parts = explode("/", $url);
$image_name = array_pop($url_parts);
Now you have just the image filename. Do the query (which I shall leave up to you, along with any validation methods and checks for real files at the address, etc.).
If it comes up with results:
header('Content-type: image/jpeg');
header('Content-Disposition: inline; filename="adorablepuppy.jpg"');
print($image_blog);
otherwise:
header("HTTP/1.0 404 Not Found");
FYI: I have no idea if this would be bad in terms of performance. But it would allow you to do what I think you want, which is output the image as though it were a flat image file on the server using a simple image element. I'm inclined to agree that BLOBs are not the best way to go, but this does avoid any cross-browser issues.
I believe that the issue that you are encountering is an issue with encoding. This resource claims that you can use the print function.
Just get the image from the database. And print it using the correct headers.
$image = mysql_fetch_array(...)
header("Content-type: image/jpeg"); // change it to the right extension
print $image['data'];
For performance reasons... this is not advisable. There are several reasons to put images in databases but the most common are:
a) keeping them indexed (duh!)
You can do this by storing the images flat on the server and just indexing the image filename.
b) keeping the image hidden/protected
Flickr and alike still store the images flat on the server and use a different approach. They generate a URL thats hard to find.
This link points to a protected image on my account. You can still access it once you know the correct URL. Try it!
farm2.static - a farm optimized for delivering static content
1399 - perhaps the server
862145282 - my username
bf83f25865_b - the image
In order to find all my secret images any user can hard hit Flickr with the above address and change the last part. But it would take ages and the user would probably be blocked for hammering the server with thousands of 404s.
That said there is little reason to store images on BLOBs.
Edit:Just a link pointing to someone that explained much better than I did why BLOB is not the way to go when storing images.

Categories