title: Signature does not match using Signed Url with GCS
body: <p>I intend to let the users of my application upload files directly to GCS, for which I am using a <a href="https://cloud.google.com/storage/docs/xml-api/put-object-upload" rel="nofollow noreferrer">PUT request</a> with a signed url. My code in python looks like this:</p>
  
  <pre class="lang-py prettyprint-override"><code>def get(self):
      base_url = 'https://storage.googleapis.com/' + self.get_bucket_name()
      expiration = utils.unix_time_secs(datetime.now() + timedelta(hours=1))
  
      string_to_sign = (  'PUT' + "\n" +
                          '' + "\n" +
                          '' + "\n" +
                          str(expiration) + "\n" +
                          '' + "\n" +
                          'my-bucket.appspot.com')
  
      signed_string = app_identity.sign_blob(string_to_sign)[1]
      signature = base64.b64encode(signed_string)
      signature = urllib.quote(signature, safe='')
      google_access_id = app_identity.get_service_account_name()
  
      params = '?GoogleAccessId={0}&amp;Expires={1}&amp;Signature={2}'.format(
                          google_access_id, expiration, signature)
  
  
      self.template_values['base_url'] = base_url
      self.template_values['params'] = params
      self.render('testA.html')
  </code></pre>
  
  <p>On the client side, I use an XMLHttpRequest to send the file to GCS:</p>
  
  <pre class="lang-js prettyprint-override"><code>function gCloud (base_url, params, callback) {
      var xhr = new XMLHttpRequest();
      var file = document.querySelector('#fotos').files[0]
  
      //Here goes an event listener (callback)
  
      url = base_url + '/' + file.name + params
      xhr.open("PUT", url, true);
      xhr.setRequestHeader("Content-Type", file.type)
      xhr.send(file)
  }
  </code></pre>
  
  <p>The problem is that when I send this request I get a 403 Forbidden Error that says that the calculated signature did not match the one I provided. It is probably a dumb error, but I can't get this to work. What could be the problem?</p>
  
  <p>EDIT:</p>
  
  <p>I tried using google-cloud-python, and tried this code (which worked):</p>
  
  <pre class="lang-py prettyprint-override"><code>def get(self):
      bucket = storage.Client().get_bucket(self.get_bucket_name())
      blob = bucket.blob('Yosemite.jpg')
  
      expiration = utils.unix_time_secs(datetime.now() + timedelta(hours=1))
      base_url = blob.generate_signed_url(expiration, "PUT", 'image/jpeg')
      self.template_values['base_url'] = base_url
      self.render('testA.html')
  </code></pre>
  
  <p>The problem now is that since 'generate_signed_url' is a method of the Blob class it already assumes I know the unique path of the object to create the url, like in blob = bucket.blob('Yosemite.jpg'), which I don't. What if the user wants to upload Space.jpg? Instead of creating my-bucket/Space.jpg, Yosemite.jpg it will be overwritten, so I will have Yosemite.jpg and if I open the image it will actually be Space.jpg. How can I solve this?</p>
  
  <p>Plus, if I don't include Content-Type='image-jpeg' in the 'generate_signed_url' function, the signature will not match. What if the user uploads a png instead?</p>