Search code examples
phpwebcam

Uploaded image taken from webcam is corrupted when uploaded to server


I am trying to upload image taken from webcam. I use canvas for showing that image and send base64_encoded json data by POST method to PHP and therefore in PHP decode the data and try to create an image by file_put_contents. But the uploaded image is corrupted every time. I used header("Access-Control-Allow-Origin: *") in PHP also. I also checked that the file_get_contents is enabled in the server. What may be the error? Please help.

My code is:

 JS:

// Trigger photo take

var imagedata;
document.getElementById('snap').addEventListener('click', function() {
   $('#canvas').show();
   context.drawImage(video, 0, 0, 640, 480);
   $('#upload-button').removeAttr("disabled");
   var image = new Image();
   image.src = canvas.toDataURL();
   imagedata = image.src;
   $('#webimage').val(imagedata);
}); 

PHP:
header("Access-Control-Allow-Origin: *");
$input_data = json_decode(trim(file_get_contents('php://input')), true);
$base = $input_data['image'];
$destination_directory = "uploads/";
$file_name  =   time();
$file_name = $file_name.'.png';
$targetPath = $destination_directory . $file_name;
$input_data = base64_decode($base);
file_put_contents($targetPath, $input_data);

Solution

  • Did you ever inspect the data url of an image? It looks like this:

    image/gif;base64,R0lGODlhyAAiALM...DfD0QAADs=
    

    As you can see the actual base64 encoded representation of the binary content of the image starts after the comma. All you have to do is change:

    $base = $input_data['image'];
    

    to:

    // php >= 5.4
    $base = explode(',', $input_data['image'])[1];
    
    // php < 5.4
    list (, $base) = explode(',', $input_data['image']);
    

    so the base64_decode function receives proper base64 string.

    You are also missing proper validation inside your script:

    • validate JSON input was decoded properly
    • validate image key exists in the resulting array
    • validate base64_decode did decode the string
    • validate resulting image is a valid image (malicious users can embed PHP code for instance inside the image)

    This way you can be 99% sure your server won't get compromised in the future.