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.

Reply via email to