1

I have a database table which contains receipt images, encoded into BLOB data in PHP. The table has the following columns and data:

id   | ownerid | file | filename            | size   | type       | fileerror
-----|---------|------|---------------------|--------|------------|-----------
1644 |       9 | BLOB | 2014-03-0714.30.jpg | 996379 | image/jpeg |      NULL

The file type was captured on original upload via a webform using one of either iMagick or GD, converted to a blob, and stored in the database.

The schema may have been converted from MyISAM to InnoDB at some point. The encoding may have been converted from Latin1 to UTF8-unicode-ci at some point. It may also have always been set thus.

I have subsequently tried all of the methods of converting the BLOB back to an image I can think of, however I never end up with an image.

I've tried using Imagick::readImageBlob($myBlob) and ended up with a big fat file which doesn't want to be an image, and I've tried using imagecreatefromstring($myBlob).

I'm using file_put_contents() to save the file.

I gather BLOBs are binary, and should stay binary, and the encoding should not effect them... however I cannot get my blobs to be pictures anymore.

How can I figure out if:

  1. My binary blobs are corrupted in the database, and I should give up.
  2. My binary blobs are fine thanks, and my PHP skills are failing me.
  3. Some kind of character encoding thing is happening behind the scenes in php I can fix.

I just tried saving the blob straight to a file from mysql workbench, and that didn't help either.

Edit: A little taste of blob (taken from the file I dumped, via chrome)

/9j/4FwwEEpGSUZcMAEBAVwwYFwwYFwwXDD/4Vww8kV4aWZcMFwwTU1cMCpcMFwwXDAIXDAMAVwwXDADXDBcMFwwAQmQXDBcMAEBXDADXDBcMFwwAQcsXDBcMAEPXDACXDBcMFwwBE
Tim Ogilvy
  • 1,923
  • 1
  • 24
  • 36
  • Thanks for the edit @Ben. – Tim Ogilvy Mar 29 '16 at 15:23
  • 1
    No worries, I felt bad for removing the picture of your head in the sand but this is SO and if I didn't, someone else would... – Ben Mar 29 '16 at 15:24
  • Maybe post a snippet of the beginning 100 characters or so of the blob? – AbraCadaver Mar 29 '16 at 15:24
  • Thanks @AbraCadaver, have done. I made the processor fan on my macbook go a little crazy when I tried to get the whole thing! Hopefully that's enough. – Tim Ogilvy Mar 29 '16 at 15:37
  • Also just a shot, try a `base64_decode()`. – AbraCadaver Mar 29 '16 at 15:47
  • 1
    I'd start by having a close look at first bytes, e.g. `SELECT HEX(file)`, to see if they feature a proper signature. Also, `BLOB` has a max size of around 65K and your original file appears to be almost 1MB large—it could just be truncated. – Álvaro González Mar 29 '16 at 15:48
  • @ÁlvaroGonzález Thanks!, the file is probably an image taken on someone's iPhone so I expect it was at least 3mb originally. Technically speaking its a longblob rather than just a blob, looking more closely at the schema – Tim Ogilvy Mar 29 '16 at 15:51

2 Answers2

4

Based on the BLOB data you posted, the file magic number /9j/4 is jpeg;base64, so this should get part of the way there:

$data = base64_decode($data)
file_put_contents('2014-03-0714.30.jpg', $data);

The data looks like a JPEG:

 ╪ α\0►JFIF\0☺☺☺\0`\0`\0\0 ß\0≥Exif\0\0MM\0*\0\0\\0♀☺\0\0♥\0\0\0☺       É\0\0☺☺\0♥\0\0\0☺,\0\0☺☼\0☻\    0\0\0♦

However the slashes \ look suspect so the data may have been escaped before being encoded, so try:

$data = stripslashes(base64_decode($data));

Which looks better:

 ╪ α ►JFIF ☺☺☺ ` `   ß ≥Exif  MM *  ♀☺  ♥   ☺   É  ☺☺ ♥   ☺,  ☺☼ ☻   ♦

And for comparison, similar to Wikipedia's Stonehenge:

 ╪ α ►JFIF ☺☻☺ x x   ß▬Exif   MM *  ☺↕  ♥   ☺☺ ☺→♣  ☺ b☺←♣ ☺j☺(♥ ☺☻ ☺1
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
  • It was certainly a jpeg once. This looks promising! I will let you know how I go with that. Must sleep for now. Thanks again! – Tim Ogilvy Mar 29 '16 at 15:52
  • I got caught out because the demo I posted was base64 encoded, however when pulling it from the database in PHP it was not. Stripslashes was the missing part. I now have images again. Happy days! – Tim Ogilvy Mar 30 '16 at 01:13
0

Try

file_put_contents('/path/to/file.jpg', $myBlob);

Or

$myImage = imagecreatefromstring($myBlob);
imagejpeg($myImage, '/path/to/file.jpg', 80);
cmorrissey
  • 8,493
  • 2
  • 23
  • 27
  • 1
    `Fatal error: Call to undefined function put_file_contents()` – AbraCadaver Mar 29 '16 at 15:38
  • Thanks! I'm pretty sure I tried both of these at last attempt, however I'll give them one more go and report back to you with the results. It's ZzZzZ o'clock here in Melbourne Australia, so I will have to update you when the sun comes back around, but thanks! – Tim Ogilvy Mar 29 '16 at 15:39