Hello Scott, the "StringToSign" field tells you what it expects the canonical string to look like. You should double-check that the string your client uses is exactly the same (including any whitespace).
For this kind of technical question I also recommend that you post it to Stack Overflow using one of the tags <https://cloud.google.com/support/docs/community> monitored by our community technical support team. On Sunday, November 19, 2017 at 2:06:17 PM UTC-5, Scott Campbell wrote: > > 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=1234567890...@developer.gserviceaccount.com&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 google-appengine+unsubscr...@googlegroups.com. To post to this group, send email to google-appengine@googlegroups.com. 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/6e2667e6-f7b9-41d0-a855-caa0473a2264%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.