生成签名地址上传和下载OSS对象

本文介绍通过Object Table生成签名地址以实现OSS对象的上传和下载。

背景信息

MaxComputeObject Table可用来处理OSS上非结构化数据,Object TableSQL计算可以帮助用户精准筛选待处理的图片列表(如跟进时间、名称、大小等),并将其传递给第三方服务进行处理。然而,这些计算服务在下载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

三层模型下完整表全路径:<project>.<schema>.<table>

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表示下载。

  • PUT表示上传。

默认值是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_nameschema_name替换成您实际的项目名称和Schema名称。

ECS通过生成预签名URL下载OSS对象

步骤一:生成下载OSS对象的URL

  1. 登录OSS控制台,上传测试数据signedget.txtobject_table_folder目录下。具体操作请参见OSS上传文件

  2. 使用MaxCompute客户端(odpscmd)或使用DataWorks创建MaxCompute SQL节点来创建Object Table并刷新元数据信息缓存。

    -- Object TableMaxCompute项目中支持Schema功能,开启三层模型。 
    set odps.namespace.schema=true;
    
    -- 选择对应MaxCompute项目。 
    use <project_name>;
    
    -- 选择对应的schema。 
    use schema <schema_name>;
    
    -- Object TableMaxCompute项目中支持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;
  3. 查询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****   |
    +------------+------------+------------+---------------+---------------+------------+--------------+------------+--------------------+
  4. 通过函数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  |
    +------------+
  5. 查询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服务器下载

  1. 登录ECS控制台,单击左侧导航栏实例与镜像 > 实例

  2. 切换杭州地域,选择目标实例,单击远程连接,通过Workbench连接ECS实例。

  3. 在终端对话框执行如下指令,下载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=****"

    返回结果如图所示:

    yuddd

ECS通过生成预签名URL上传OSS对象

步骤一:生成上传OSS对象的URL

使用已创建的Object Tabletest_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服务器上传

  1. 使用已创建的ECS服务器,准备测试数据signedput.txt,并上传至opt目录下。

  2. Workbench终端执行如下指令,上传数据至OSS。

    -- 切换至opt目录下
    cd /opt
    
    --通过签名URL上传signedput.txtOSS。
    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=****"

    返回结果如图所示:

    opopopo

步骤三:查询Object Table元数据信息

  1. 刷新表缓存,指令如下:

    ALTER TABLE test_get_signed_url_from_oss REFRESH METADATA;
  2. 查询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****   |
    +------------+------------+------------+---------------+---------------+------------+--------------+------------+--------------------+
  3. 通过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语法开关。