本文介绍通过Object Table生成签名地址以实现OSS对象的上传和下载。
背景信息
MaxCompute的Object Table可用来处理OSS上非结构化数据,Object Table和SQL计算可以帮助用户精准筛选待处理的图片列表(如跟进时间、名称、大小等),并将其传递给第三方服务进行处理。然而,这些计算服务在下载OSS对象时需要具备相应的权限,通常的方式是通过永久AK/SK或服务角色扮演,但这些方式存在一定的弊端:
永久AK/SK涉及安全隐患,用户需将AK/SK存储于第三方服务中,一旦泄露,将面临较高的风险。
服务扮演角色通常指的是MaxCompute在访问OSS时所扮演的角色,而第三方则需要单独扮演其他角色,增加了代码的复杂性。
目前OSS支持使用预签名URL下载或预览文件。只要该URL在签名时的有效期足够长,用户即可通过HTTP协议直接访问,操作非常简便。除了可以生成用于下载的URL外,还可以生成用于上传数据的URL,用户可根据需求自行选择其用途。
GET_SIGNED_URL_FROM_OSS
生成用于下载或上传OSS数据的免密签名URL,使用户通过HTTP协议直接读写OSS文件。
使用限制
目前只支持通过OSS内网方式创建Object Table。
目前在MaxQA查询加速中暂时不支持使用。需添加参数
set odps.mcqa.disable=true;
与SQL语句一并运行。
注意事项
如果您的OSS Bucket启用了阻止公共访问功能,则无法通过
get_signed_url_from_oss
方法生成公网可访问的签名地址。请确保Bucket权限配置允许您生成和使用签名地址。
函数定义
STRING get_signed_url_from_oss (
STRING <fullTableName>,
STRING <ossKey>,
INT <timeToLiveSeconds>,
DATETIME <expiration>,
STRING <httpMethod>
)
参数说明
参数 | 是否必填 | 数据类型 | 说明 | 默认值 |
fullTableName | 是 | STRING | 三层模型下完整表全路径: | 无 |
ossKey | 是 | STRING | 对象key,用来定位表中的对象。通常为Object Table表中的key列。 | 无 |
timeToLiveSeconds | 否 | INT | 签名URL的有效期时长,最小1秒,最大7天(604800秒)。 | 默认为3600秒。 |
expiration | 否 | DATETIME | 签名URL过期时间点。最小比当前时间大1秒,最大比当前时间多7天(604800秒)。 | 默认比当前时间大3600秒。 |
httpMethod | 否 | STRING | 生成URL之后使用方式,是下载(读取OSS数据)还是上传(数据写入OSS)。
| 默认值是GET用来下载。 |
返回值
返回值为STRING类型。
其他场景函数定义
最精简模式,3600秒过期时长,默认GET。
STRING get_signed_url_from_oss ( STRING <fullTableName>, STRING <ossKey> );
自定义过期时长,默认GET。
STRING GET_SIGNED_URL_FROM_OSS( STRING <fullTableName>, STRING <ossKey>, INT <timeToLiveSeconds> );
自定义过期时长以及读写用途。
STRING GET_SIGNED_URL_FROM_OSS( STRING <fullTableName>, STRING <ossKey>, INT <timeToLiveSeconds>, STRING <httpMethod> );
自定义过期时间点,默认GET。
STRING GET_SIGNED_URL_FROM_OSS( STRING <fullTableName>, STRING <ossKey>, DATETIME <expiration> );
自定义过期时间点以及读写用途。
STRING GET_SIGNED_URL_FROM_OSS( STRING <fullTableName>, STRING <ossKey>, DATETIME <expiration>, STRING <httpMethod> );
使用示例
以杭州地域为例,OSS内网域名
oss-cn-hangzhou-internal.aliyuncs.com
,生成的签名地址也在内网环境,其他阿里云服务可以正常访问OSS地址。使用杭州地域的阿里云ECS服务器通过签名URL来下载和上传OSS数据。
project_name
和schema_name
替换成您实际的项目名称和Schema名称。
在ECS通过生成预签名URL下载OSS对象
步骤一:生成下载OSS对象的URL
登录OSS控制台,上传测试数据signedget.txt至object_table_folder目录下。具体操作请参见OSS上传文件。
使用MaxCompute客户端(odpscmd)或使用DataWorks创建MaxCompute SQL节点来创建Object Table并刷新元数据信息缓存。
-- Object Table在MaxCompute项目中支持Schema功能,开启三层模型。 set odps.namespace.schema=true; -- 选择对应MaxCompute项目。 use <project_name>; -- 选择对应的schema。 use schema <schema_name>; -- Object Table在MaxCompute项目中支持2.0数据类型系统。 set odps.sql.type.system.odps2=true; -- 目前在MaxQA查询加速中暂不支持使用。 set odps.mcqa.disable=true; -- 创建Object Table。 CREATE OBJECT TABLE IF NOT EXISTS test_get_signed_url_from_oss LOCATION 'oss://oss-cn-hangzhou-internal.aliyuncs.com/object-table-test/object_table_folder/'; -- 刷新表缓存。 ALTER TABLE test_get_signed_url_from_oss REFRESH METADATA;
查询Object Table表中的元数据信息。
SELECT * FROM test_get_signed_url_from_oss;
返回结果如下:
+------------+------------+------------+---------------+---------------+------------+--------------+------------+--------------------+ | key | size | type | last_modified | storage_class | etag | restore_info | owner_id | owner_display_name | +------------+------------+------------+---------------+---------------+------------+--------------+------------+--------------------+ | signedget.txt | 38 | Normal | 2025-06-04 01:36:52 | Standard | 96D8258845DAB51BC9B****6E61A2563 | NONE | 13**** | 13**** | +------------+------------+------------+---------------+---------------+------------+--------------+------------+--------------------+
通过函数GET_DATA_FROM_OSS读取对象数据。
SELECT string( get_data_from_oss( '<project_name>.<schema>.test_get_signed_url_from_oss', key ) ) FROM test_get_signed_url_from_oss;
返回结果如下:
+------------+ | _c0 | +------------+ | test maxcompute download files by url | +------------+
查询Object Table并生成签名地址URL。
SELECT get_signed_url_from_oss( '<project_name>.<schema_name>.test_get_signed_url_from_oss', key) FROM test_get_signed_url_from_oss;
返回结果如下:
+------------+ | _c0 | +------------+ | http://object-table-test.oss-cn-hangzhou-internal.aliyuncs.com/object_table_folder%2Fsignedget.txt?Expires=17490****&OSSAccessKeyId=STS.****&Signature=****&security-token=**** | +------------+
步骤二:通过ECS服务器下载
登录ECS控制台,单击左侧导航栏 。
切换杭州地域,选择目标实例,单击远程连接,通过Workbench连接ECS实例。
在终端对话框执行如下指令,下载OSS对象:
-- 切换至opt目录下 cd /opt --通过签名URL下载对应OSS对象。 curl -o /opt/ecs_signed.txt "http://object-table-test.oss-cn-hangzhou-internal.aliyuncs.com/object_table_folder%2Fsignedget.txt?Expires=17490****&OSSAccessKeyId=STS.****&Signature=****&security-token=****"
返回结果如图所示:
在ECS通过生成预签名URL上传OSS对象
步骤一:生成上传OSS对象的URL
使用已创建的Object Table表test_get_signed_url_from_oss
。查询Object Table并生成签名地址URL。代码如下所示:
SELECT get_signed_url_from_oss(
'<project_name>.<schema_name>.test_get_signed_url_from_oss',
key,
3600,
'PUT'
)
FROM test_get_signed_url_from_oss;
返回结果如下:
+------------+
| _c0 |
+------------+
| http://object-table-test.oss-cn-hangzhou-internal.aliyuncs.com/object_table_folder%2Fsinged_put?Expires=17490****&OSSAccessKeyId=****&Signature=****&security-token=**** |
+------------+
步骤二:通过ECS服务器上传
使用已创建的ECS服务器,准备测试数据signedput.txt,并上传至opt目录下。
在Workbench终端执行如下指令,上传数据至OSS。
-- 切换至opt目录下 cd /opt --通过签名URL上传signedput.txt至OSS。 curl -X PUT -T /opt/signedput.txt -i "http://object-table-test.oss-cn-hangzhou-internal.aliyuncs.com/object_table_folder%2Fsinged_put?Expires=17490****&OSSAccessKeyId=****&Signature=****&security-token=****"
返回结果如图所示:
步骤三:查询Object Table元数据信息
刷新表缓存,指令如下:
ALTER TABLE test_get_signed_url_from_oss REFRESH METADATA;
查询Object Table表中的元数据信息,指令如下:
SELECT * FROM test_get_signed_url_from_oss;
返回结果如下:
+------------+------------+------------+---------------+---------------+------------+--------------+------------+--------------------+ | key | size | type | last_modified | storage_class | etag | restore_info | owner_id | owner_display_name | +------------+------------+------------+---------------+---------------+------------+--------------+------------+--------------------+ | signedget.txt | 38 | Normal | 2025-06-03 01:36:52 | Standard | 96D8258845DAB51BC****546E61A2563 | NONE | 13**** | 13**** | | singed_put | 44 | Normal | 2025-06-03 19:31:23 | Standard | F5EA64DF895CF08C3****7D3FD09F12 | NONE | 13**** | 13**** | +------------+------------+------------+---------------+---------------+------------+--------------+------------+--------------------+
通过GET_DATA_FROM_OSS,读取OSS对象数据。指令如下:
SELECT string( get_data_from_oss( '<project_name>.<schema_name>.test_get_signed_url_from_oss', key ) ) FROM test_get_signed_url_from_oss;
返回结果如下:
+------------+ | _c0 | +------------+ | test maxcompute download files by url | | test Object Table upload file to oss by url | +------------+
常见问题
问题1:函数中的表路径和底层被查询的表路径不同
报错信息
ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: Can't do ObjectTableTwoPhasesSplitting process (Caused by: java.lang.IllegalArgumentException: The first arg[xxx.default.test_get_signed_url_from_ossxxxxxx] of function GET_SIGNED_URL_FROM_OSS({object_table_full_name}, {object_key}, ...) can't be found in the underlying object table scans[xxx.default.test_get_signed_url_from_oss])
。错误描述
test_get_signed_url_from_ossxxxxxx
该表名不存在或者与SQL中被访问的表名不同。解决方案
写入真实存在且相同的Object Table表名,且用
project.schema.table
格式。
问题2:timeToLiveSeconds参数值不正确
报错信息
ODPS-0121095:[1,8] Invalid argument - The parameter <timeToLiveSeconds> of the function GET_SIGNED_URL_FROM_OSS() you specified (0) is invalid, it should be in the range [1, 604800]
。错误描述
函数中的过期时长(timeToLiveSeconds)参数值不正确,必须在[1, 604800]之间。
解决方案
需写入正确范围内的过期时长。
问题3: HttpMethod参数值不正确
报错信息
ODPS-0121095:[1,8] Invalid argument - The parameter <httpMethod> of the function GET_SIGNED_URL_FROM_OSS() you specified 'PU' is invalid, it can only be 'GET' or 'PUT'
。错误描述
函数中的HttpMethod参数值不正确。
解决方案
HttpMethod参数值只能为GET或者PUT。
问题4:签名时间太短,链接已超时
报错信息
执行curl命令报错Request has expired。
错误描述
签名URL时间太短,访问时已经过期。
解决方案
expiration参数值需要设置的合理一些,过长或过短都不建议。
问题5:未开启三层模型语法开关
报错信息
ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed: Can't do ObjectTableTwoPhasesSplitting process (Caused by: java.lang.IllegalArgumentException: Invalid parameter of object table full name[str=xxx.test_get_signed_url_from_oss], which should be split up into 3 parts by '.' like '${project}.${schema}.${table}')
。错误描述
未打开Schema语法开关,无法识别
project.schema.table
语法格式。解决方案
函数SQL前需加上
set odps.namespace.schema=true;
打开Schema语法开关。