Dan
Dan

Reputation: 367

How to handle image being posted to PHP that wasn't base64 encoded?

I am trying to provide retroactive support for a desktop client that posts image data incorrectly to my PHP form.

The problem is that the image data posted hasn't been base64 encoded and I can't change the distributed clients, so I'm wondering if I can do something server side.

The data for the image when written to the server via

file_put_contents($filePath,$_POST['rawImageData']);

Results in a corrupted JPEG (I know that all images uploaded are JPEGs).

The encoding appears to be the default HTTP POST encoding, ISO-8859-1.

I've tried converting the posted data using iconv, utf_decode, mb_convert_encoding and a couple of others with no luck.

Is it possible to recover in this situation?

Upvotes: 4

Views: 542

Answers (1)

Austin
Austin

Reputation: 3328

PHP is probably improperly filling the $_POST array because it is interpreting the JPEG data as form data which might contain & characters or other things that will confuse it. If you manually read the input stream instead of relying on $_POST, you should be able to recover your data.

I wrote some quick code to try to reproduce your issue and test this:

client.php

This code emulates your client; it just reads a JPEG file and writes it raw over a POST request.

$url = 'http://localhost/server.php';
$input = __DIR__ . '/input.jpg';

$parts = parse_url($url);
$sock = fsockopen($parts['host'], 80);

$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".(filesize($input) + strlen("rawImageData="))."\r\n";
$out.= "\r\n";
$out.= "rawImageData=";

fwrite($sock, $out);
$fd = fopen($input, 'r');
stream_copy_to_stream($fd, $sock);
fclose($fd);
fclose($sock);

server.php (version 1)

This tries to use the $_POST value as your code does.

$tmp = "/tmp/output.jpg";
file_put_contents($tmp, $_POST['rawImageData']);

server.php (version 2)

This reads the raw input stream from the POST body.

$tmp = "/tmp/output.jpg";
$fd = fopen('php://input', 'r');
fread($fd, strlen("rawImageData=")); //throw this data out
$out = fopen($tmp, 'w');
stream_copy_to_stream($fd, $out);
fclose($out);
fclose($fd);

For input.jpg I used an ~10k JPEG file from Wikipedia.

Result

Server version 1 writes only about 50 bytes to output.jpg, and when I try to open it with a viewer, I get a corrupt JPEG error. Server version 2 writes the full 10k bytes, and my JPEG viewer shows the image just fine.

Upvotes: 6

Related Questions