I am trying to upload audio files on the Client-Side directly to my Google 
Cloud Storage bucket, for the purpose of avoiding a server-side upload 
(which has file size limits).

My Issue: I am getting a 403  SignatureDoesNotMatch  error on upload. 

Here is the error from the response:


   1. <Error>
      1. <Code>SignatureDoesNotMatch</Code>
      2. <Message>The request signature we calculated does not match the 
      signature you provided. Check your Google secret key and signing method.
      </Message>
      3. <StringToSign>PUT audio/mp3 1511112552 
      /bucketname/pathtofile/019%20-%20top%20cntndr%20V1.mp3</StringToSign>
      4. </Error>
   


I have created a signed url. It looks like this:

https://storage.googleapis.com/google-testbucket/testdata.txt?GoogleAccessId=
[email protected]&Expires=1331155464&Signature=BCl
z9e4UA2MRRDX62TPd8sNpUCxVsqUDG3YGPWvPcwN%2BmWBPqwgUYcOSszCPlgWREeF7oPGowkeKk
7J4WApzkzxERdOQmAdrvshKSzUHg8Jqp1lw9tbiJfE2ExdOOIoJVmGLoDeAGnfzCd4fTsWcLbal9
sFpqXsQI8IQi1493mw%3D


The signed url is built following the guidlines found in the Google Docs 
here 
https://cloud.google.com/storage/docs/access-control/create-signed-urls-program

However, the client-side javascript portion of handling this signed url is 
very unclear in the documentation.




Here is my python code to create and return the signed url.


GOOGLE_SERVICE_CREDENTIALS = 'google-service-credentials.json'

def get_signed_url(request):
    filename = request.GET.get('filename')
    expiration = request.GET.get('expiration')
    type = request.GET.get('type')
    signed_url = CloudStorageSignedURL(
                method='PUT',
                file_name=filename,
                expiration_m=expiration,
                content_type=type
                )
    signed_url = signed_url.sign_url()


    return JsonResponse({ 'signed_url': signed_url })






class CloudStorageSignedURL(object):


    def __init__(self, method, file_name, expiration_m, content_type):
        self.HTTP_method = method
        self.content_type = 'content-type: ' + content_type
        self.expiration = int(expiration_m)
        self.file_name = file_name


    def sign_url(self):


        expiration_dt = datetime.utcnow() + timedelta(minutes=self.
expiration)
        expiration = int(time.mktime( expiration_dt.timetuple() ))
        bucket_path = '/' + settings.CLOUD_STORAGE_BUCKET + '/dev/tests/' + 
self.file_name
        signature_string = self.HTTP_method + '\n' + '\n' + self.content_type 
+ "\n" + str(expiration) + '\n' + bucket_path
        print(signature_string)
        creds = ServiceAccountCredentials.from_json_keyfile_name(
GOOGLE_SERVICE_CREDENTIALS)
        client_email = creds.service_account_email
        signature = creds.sign_blob(signature_string)[1]
        encoded_signature = base64.urlsafe_b64encode(signature).decode(
'utf-8')
        base_url = settings.CLOUD_STORAGE_ROOT + 'dev/tests/' + self.
file_name


        return base_url + '?GoogleAccessId=' + client_email + '&Expires=' + 
str(expiration) + '&Signature=' + encoded_signature






*Client-side Javascript to upload the file*

import $ from 'jquery';
import axios from 'axios';



$("document").ready( () => {
  console.log('window loaded');


  $("#id_audio_file").change(function() {

    const file = this.files[0]

    const url = window.location.href.replace('submit/', 'upload/');
    $.get(url + `?filename=${file.name}&expiration=10&type=${file.type}`, (
data) => {
      upload(data.signed_url, file);
    })

  });
});



function upload(url, file) {

  const config = {
    headers: {
      'Content-Type': file.type,
    }
  }

  axios.put(url, file, config)
    .then(function (res) {
      console.log(res);
    })
    .catch(function (err) {
      console.log(err);
    });
}




I really feel like I covered all the bases here, but I am obviously missing 
something minute.  Any help would be greatly appreciated!

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/google-appengine.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/google-appengine/41387516-152e-4a24-83b0-4013289e24e0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
  • [google-appengine... Scott Campbell

Reply via email to