为指定对象请求生成带会话签名的 URL。接收方可在授权与有效期允许的范围内使用该 URL 发起请求,无需持有基础密钥。生成 URL 可能先发起 CreateSession 请求,并非始终是纯本地操作。
注意事项
URL 生成阶段可能因配置、凭据或有效期要求抛出异常,处理方式见 Python SDK 异常处理。
URL 含会话令牌及签名,应作为临时凭据保管,通过受控渠道交付,不输出完整 URL 到终端、日志或错误报告。HTTP 库异常也可能包含 URL,记录异常前应脱敏。
GET / HEAD 默认使用独立的 ReadOnly 会话,不复用数据请求中的 ReadWrite 凭据。PUT 请求需要 ReadWrite 权限;只读会话不能用于上传。生成成功不代表对象存在,也不代表文件内容已上传。
Expired 单位为秒,必须为正。SDK 会要求会话凭据剩余寿命覆盖请求的签名时长;无法获得足够长的有效凭据时本地报错,不会静默缩短 Expired。实际访问还受凭据有效性和服务端授权状态约束,不保证一直可用到设置的最后一秒。
URL 在有效期和权限允许范围内可以重复使用,不是一次性链接。
URL 生成后不会随 SDK 刷新凭据而自动更新。到期后需重新生成并交付;不要手工修改 URL 中的有效期或令牌。
必须按签名时的方法、对象路径、域名、查询参数及请求头发起请求,不随意追加参数、重编码 URL 或替换成 IP 地址。签入 Headers 的字段须由接收方按相同值携带;仅持有 URL 并不自动补齐这些头。
Headers 使用真实 HTTP 头名,例如 x-cos-forbid-overwrite;这里不是 put_object 的 ForbidOverwrite 等 SDK 参数名称。上传防覆盖需在生成 URL 时签入该头,并在实际 PUT 请求中携带。
对象键末尾 / 严格区分类型。GET / HEAD 类型不匹配返回 HTTP 404,DELETE 类型不匹配按对象不存在返回 204。PUT 文件不能覆盖同名目录;创建目录需使用尾斜杠键、空请求体及 Content-Length: 0,不附加内容类型或自定义元数据。
高性能桶不支持对象版本。Params 中的 versionId 或不支持的版本、回调参数会在本地报错。签名不会使下载条件头具备服务端未实现的一致性保护。
本页展示 GET、HEAD、PUT、DELETE 对象请求。Headers/Params 应遵循对应已文档化接口的契约;生成 URL 不代替服务端对请求的校验。
请求
调用形式
url = client.get_session_presigned_url(Bucket=bucket, Key=key, Method='GET', Expired=300)
参数说明
参数 | 说明 | 类型 | 是否必选 |
Bucket | 高性能桶完整名称,例如 examplebucket-x--1250000000 | string | 是 |
Key | 对象键,末尾 / 严格区分文件与目录 | string | 是 |
Method | HTTP 方法,本页使用 GET、HEAD、PUT、DELETE | string | 是 |
Expired | 请求的签名有效期,正整数,默认 300 秒 | int | 否 |
Params | 签入 URL 的查询参数,默认空字典;令牌由 SDK 添加 | dict | 否 |
Headers | 需签名的 HTTP 请求头;使用真实头名,默认空字典 | dict | 否 |
Mode | ReadOnly 或 ReadWrite;GET/HEAD 默认 ReadOnly,其余缺省取客户端 SessionMode | string | 否 |
SignHost | 是否签入 Host,建议显式 True 并保持原域名 | bool | 否 |
也可使用通用入口,Rapid 桶上会采用相同的会话预签名流程:
url = client.get_presigned_url(Bucket=bucket, Key=key, Method='GET', Expired=300)url = client.get_presigned_download_url(Bucket=bucket, Key=key, Expired=300)
通用入口不接收 Mode;需要显式选择权限模式时使用 get_session_presigned_url。普通桶的通用预签名行为保持原有规则。
响应
返回字符串 URL。GET/HEAD 等签名仅授权相应请求,不下载内容;PUT 签名不会发送请求体。接收方必须能访问 URL 对应的服务入口。
错误码
实际案例
生成下载 URL,并在当前进程中使用;实际交付时通过受控渠道传递 url,不记录其完整内容:
# -*- coding: utf-8 -*-import osfrom qcloud_cos import CosConfig, CosS3Client# 高性能桶经 VPC 内网 HTTP 80 端口接入,SDK 的网关 DNS 负载均衡也仅对 HTTP 请求生效;SDK 默认 https,此处需显式指定 http。config = CosConfig(Scheme='http', Region='ap-guangzhou',SecretId=os.environ['COS_SECRET_ID'],SecretKey=os.environ['COS_SECRET_KEY'],Token=os.environ.get('COS_SECURITY_TOKEN'),EnableRapidDomain=True)client = CosS3Client(config)bucket = 'examplebucket-x--1250000000'import requestsurl = client.get_session_presigned_url(Bucket=bucket, Key='uploads/report.bin', Method='GET',Expired=60, SignHost=True)response = Nonetry:response = requests.get(url, stream=True, timeout=30, allow_redirects=False)except requests.RequestException:pass # 请求库异常可能携带完整 URL,示例不将其输出。if response is None:raise RuntimeError('presigned download request failed')try:if response.status_code != 200:raise RuntimeError('download HTTP status: %s' % response.status_code)with open('presigned-download.bin', 'wb') as output:for chunk in response.iter_content(chunk_size=1024 * 1024):if chunk:output.write(chunk)finally:response.close()print('presigned download completed')
生成带防覆盖请求头的上传 URL,使用方须携带同一份 headers:
# -*- coding: utf-8 -*-import osfrom qcloud_cos import CosConfig, CosS3Client# 高性能桶经 VPC 内网 HTTP 80 端口接入,SDK 的网关 DNS 负载均衡也仅对 HTTP 请求生效;SDK 默认 https,此处需显式指定 http。config = CosConfig(Scheme='http', Region='ap-guangzhou',SecretId=os.environ['COS_SECRET_ID'],SecretKey=os.environ['COS_SECRET_KEY'],Token=os.environ.get('COS_SECURITY_TOKEN'),EnableRapidDomain=True)client = CosS3Client(config)bucket = 'examplebucket-x--1250000000'import requestsheaders = {'x-cos-forbid-overwrite': 'true','Content-Type': 'application/octet-stream',}url = client.get_session_presigned_url(Bucket=bucket, Key='presigned/new-file.bin', Method='PUT',Expired=60, Mode='ReadWrite', SignHost=True, Headers=headers)response = Nonetry:response = requests.put(url, data=b'hello rapid bucket', headers=headers,timeout=30, allow_redirects=False)except requests.RequestException:pass # 在 except 块外报告错误,避免异常链输出原 URL。if response is None:raise RuntimeError('presigned upload request failed')try:if response.status_code != 200:raise RuntimeError('upload HTTP status: %s' % response.status_code)finally:response.close()print('presigned upload completed')