我打算讓我的應用程序的用戶直接將文件上載到GCS,爲此我使用帶有簽名url的PUT request。我在Python代碼如下所示:使用帶有GCS的帶簽名的Url不匹配簽名不匹配
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}&Expires={1}&Signature={2}'.format(
google_access_id, expiration, signature)
self.template_values['base_url'] = base_url
self.template_values['params'] = params
self.render('testA.html')
在客戶端,我用一個XMLHttpRequest將文件發送到GCS:
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)
}
的問題是,當我把這一請求,我得到一個403表示計算出的簽名與我提供的簽名不匹配的禁止錯誤。這可能是一個愚蠢的錯誤,但我無法得到這個工作。可能是什麼問題呢?
編輯:
我嘗試使用谷歌-雲蟒,並試圖此代碼(其工作):
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')
現在的問題是,由於「generate_signed_url」是斑點的方法它已經假設我知道創建url的對象的唯一路徑,就像blob = bucket.blob('Yosemite.jpg'),我不知道。如果用戶想要上傳Space.jpg會怎麼樣? Yosemite.jpg將被覆蓋,而不是創建my-bucket/Space.jpg,因此我將擁有Yosemite.jpg,如果我打開該圖像,它實際上將是Space.jpg。我該如何解決這個問題?
另外,如果我在'generate_signed_url'函數中不包含Content-Type ='image-jpeg',則簽名將不匹配。如果用戶上傳png會怎樣?
感謝您的回答。我嘗試轉義google_access_id,但沒有解決它。我試着使用google-cloud-python庫並相應地編輯了這個問題,但是根據我的理解,該函數假設我知道諸如文件名或它的內容類型之類的內容,然後將url傳遞給用戶。我能做些什麼呢? –
OH。您正在嘗試編輯客戶端的URL以追加對象名稱?這是行不通的。整點簽名的URL是爲了防止客戶編輯請求。如果您希望用戶能夠指定對象名稱,那麼還有另一個選項:簽名的POST請求策略文檔。請參閱https://cloud.google.com/storage/docs/xml-api/post-object#policydocument –
對於這種情況,我會使用POST,我會爲其他人保留PUT。非常感謝您的回答! –