def generate_blob_download_url( self, blob: Blob, expires: int = 3600, method: str = "GET", content_disposition: str = None, extra: ExtraOptions = None, ) -> str: if extra: logger.info(messages.OPTION_NOT_SUPPORTED, "extra") key = self._get_temp_url_key() storage_public_url = self._get_server_public_url("cloudFiles") url = "%s/%s" % (storage_public_url, quote(blob.path)) base_url, object_path = url.split("/v1/") object_path = "/v1/" + object_path # Time must be in UNIX epoch format. expires_in = int(time() + expires) hmac_body = "%s\n%s\n%s" % (method.upper(), expires_in, object_path) signature = hmac.new(key.encode("utf-8"), hmac_body.encode("utf-8"), hashlib.sha1).hexdigest() parameters = { "temp_url_sig": signature, "temp_url_expires": expires_in, } # Rackspace uses query params: filename (attachment) and inline if content_disposition: disposition, params = parse_content_disposition( content_disposition) if disposition == "inline": parameters["inline"] = "" parameters["filename"] = params.get("filename", blob.name) return "%s%s?%s" % (base_url, object_path, urlencode(parameters))
def generate_blob_download_url(self, blob: Blob, expires: int = 3600, method: str = 'GET', content_disposition: str = None, extra: ExtraOptions = None) -> str: if extra: logger.info(messages.OPTION_NOT_SUPPORTED, 'extra') key = self._get_temp_url_key() storage_public_url = self._get_server_public_url('cloudFiles') url = '%s/%s' % (storage_public_url, quote(blob.path)) base_url, object_path = url.split('/v1/') object_path = '/v1/' + object_path # Time must be in UNIX epoch format. expires_in = int(time() + expires) hmac_body = '%s\n%s\n%s' % (method.upper(), expires_in, object_path) signature = hmac.new(key.encode('utf-8'), hmac_body.encode('utf-8'), hashlib.sha1).hexdigest() parameters = { 'temp_url_sig': signature, 'temp_url_expires': expires_in, } # Rackspace uses query params: filename (attachment) and inline if content_disposition: disposition, params = parse_content_disposition( content_disposition) if disposition == 'inline': parameters['inline'] = '' parameters['filename'] = params.get('filename', blob.name) return '%s%s?%s' % (base_url, object_path, urlencode(parameters))
def test_blob_generate_download_url(binary_blob, temp_file): content_disposition = settings.BINARY_OPTIONS.get("content_disposition") download_url = binary_blob.generate_download_url( content_disposition=content_disposition) assert uri_validator(download_url) response = requests.get(download_url) assert response.status_code == HTTPStatus.OK, response.text # Rackspace adds extra garbage to the header # 'attachment; filename=avatar-attachment.png; # filename*=UTF-8\\'\\'avatar-attachment.png' disposition, params = parse_content_disposition( response.headers["content-disposition"]) response_disposition = "{}; filename={}".format(disposition, params["filename"]) assert response_disposition == content_disposition with open(temp_file, "wb") as f: for chunk in response.iter_content(chunk_size=128): f.write(chunk) hash_type = binary_blob.driver.hash_type download_hash = file_checksum(temp_file, hash_type=hash_type) assert download_hash.hexdigest() == settings.BINARY_MD5_CHECKSUM
def test_parse_content_disposition(value, expected): disposition, params = parse_content_disposition(value) assert disposition == expected[0] assert params == expected[1]