0

When uploading to Google cloud storage using a PUT request with base64 data the image (PNG) does not display in the browser and says that it contains errors (when viewing in FF).

After opening the image file in a text editor I can see the base64 data "data:image/png;base64,iVBORw...", so it does not get converted to binary.

Am I meant to upload the binary or is there a way to get this to work with base64 in the HTTP body ?

Basic Code Sample.


    <?php

    $theDate    = Date(DATE_RFC822);
    $emailID    = "*******.gserviceaccount.com";
    $priv_key   = file_get_contents("*******-privatekey.p12");

    function signedURL( $filename, $bucket, $method = 'PUT' ) {
      global $emailID;
      global $priv_key;

       $signature  = "";
       $duration   = 60;
       $certs      = array();
          if (!openssl_pkcs12_read($priv_key, $certs, 'notasecret')) { echo "Unable to parse the p12 file. OpenSSL error: " . openssl_error_string(); exit(); }

        $expires = time() + $duration;
        $to_sign = ( $method . "\n\nimage/png; charset=UTF-8\n" . $expires . "\nx-goog-acl:public-read\n" . "/" . $bucket . "/" . $filename ); 
        $RSAPrivateKey = openssl_pkey_get_private($certs["pkey"]);

      if (!openssl_sign( $to_sign, $signature, $RSAPrivateKey, 'sha256' ))
      {
        error_log( 'openssl_sign failed!' );
        $signature = 'failed';
      } else {
        $signature =  urlencode( base64_encode( $signature ) );
      }

      return ('http://' . $bucket . '/' . $filename . '?GoogleAccessId=' . $emailID . '&Expires=' . $expires . '&Signature=' . $signature);
        openssl_free_key($RSAPrivateKey);
    } 

    $UploadURL = signedURL('test.png', 'mybucket.mydomain.net', 'PUT');

    //echo $UploadURL;

    ?>

    <script>
    var base64img  = "data:image/png;base64,iVB...";//snipped
    var xhr        = new XMLHttpRequest();

    xhr.open("PUT", "<?php echo $UploadURL ?>");
    xhr.setRequestHeader("Content-type", "image/png");
    xhr.setRequestHeader("x-goog-acl", "public-read"); //try to set public read on file
    xhr.setRequestHeader("Content-Length", base64img.length); // Chrome throws error
    xhr.send( base64img );
    </script>

I feel that it is possible based on things that I've read online, but I can't find any examples showing exactly the way it is done with PUT to indicate what is missing to make it work.

Tom
  • 130
  • 1
  • 8
  • I'm confused, why do you want to upload base 64 encoded says when you could simply upload the binary data? A binary upload is significantly more efficient. – Benson Jun 07 '13 at 15:40
  • Because I thought that I read somewhere that base64 data on average was about 33% smaller, but now you've said that I'm wondering if I read that wrong. If that is the case then I'll go ahead with the blob. Thanks for the reply. – Tom Jun 10 '13 at 11:50
  • 2
    o.k, I really did read it wrong.. http://stackoverflow.com/questions/9722603/storing-image-in-database-directly-or-as-base64-data?rq=1 .. :) – Tom Jun 10 '13 at 11:58
  • 1
    Yeah, you definitely don't want to b64 if you're hoping for better efficiency. Is it worth me rewriting that as an answer? – Benson Jun 10 '13 at 17:14
  • Hi, thanks again and yeah sure, is that how we close these things ?... I'm new to stack. – Tom Jun 13 '13 at 11:24
  • Yup. Once an answer has been accepted (green check mark next to the answer), the question will stick around for others to learn from. – Benson Jun 14 '13 at 17:32

1 Answers1

0

You typically want to avoid using base64 encoding unless you really need it. Encoding something in base64 incurs a size overhead, and also requires decoding before it can be used, which is effectively a CPU overhead. Essentially, you only want b64 encode something if the protocol and transport you're using can't handle binary data.

So, in your case I think the answer is to avoid base64 and just upload raw bytes. In the general case, if you do base64 encode something before storing it in Cloud Storage, you'll need to plan for a decode step in whatever software is pulling it back out.

Community
  • 1
  • 1
Benson
  • 22,457
  • 2
  • 40
  • 49