You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Label Studio集成Azure Data Lake时预签名URL生成失败求助

问题:Azure Data Lake存储集成无法生成符合Label Studio要求的预签名URL

我正在为Label Studio开发Azure Data Lake存储集成,Django后端的核心逻辑是将云存储对象解析为预签名HTTP地址,实现跨云存储提供商的文件读取。但目前遇到以下问题:

  • 调用接口{django_live_url}/api/projects/{project_pk}/next时,返回的是azure-spi://<path/to/file>格式的地址,而非预期的/tasks/\d+/presign/?fileuri=YX...格式
  • 对应的测试用例执行失败,不确定服务主体认证模式下Azure Data Lake是否支持生成HTTP可访问的预签名URI

测试用例代码

- name: stage
  request:
    method: GET
    url: '{django_live_url}/api/projects/{project_pk}/next'
  response:
    json:
      data:
        image_url: !re_match "/tasks/\d+/presign/\?fileuri=YXp1cmUtYmxvYjovL3B5dGVzdC1henVyZS1pbWFnZXMvYWJj"
    status_code: 200

当前实现的代码片段

class AzureServicePrincipalImportStorageBase(AzureServicePrincipalStorageMixin, ImportStorage):
     url_scheme = 'azure_spi'

     presign = models.BooleanField(_('presign'), default=True, help_text='Generate presigned URLs')
     presign_ttl = models.PositiveSmallIntegerField(
         _('presign_ttl'), default=1, help_text='Presigned URLs TTL (in minutes)'
     )      
(…)
     def generate_http_url(self, url):
         match = re.match(AZURE_URL_PATTERN, url)
         if match:
             match_dict = match.groupdict()
             sas_token = self.get_sas_token(match_dict['blob_name'])
             url = f"{self.get_account_url()}/{self.container}/{match_dict['blob_name']}?{sas_token}"
         return url
(…)
     def resolve_uri(self, uri, task=None):
         # 处理列表类型的URI
         if isinstance(uri, list):
             resolved = []
             for item in uri:
                 result = self.resolve_uri(item, task)
                 resolved.append(result if result else item)
             return resolved

         # 处理字典类型的URI
         elif isinstance(uri, dict):
             resolved = {}
             for key in uri.keys():
                 result = self.resolve_uri(uri[key], task)
                 resolved[key] = result if result else uri[key]
             return resolved
         elif isinstance(uri, str):
             try:
                 # 从任务数据中提取URI
                 if self.presign and task is not None:
                     sig = urlparse(uri)
                     if sig.query != '':
                         return uri
                 # 将URI解析为HTTP URL
                 http_url = self.generate_http_url(uri)
                 return http_url

             except Exception:
                 logger.info(f"Can't resolve URI={uri}", exc_info=True)

     class Meta:
         abstract = True

问题排查与修复建议

  • 核心逻辑偏差:当前resolve_uri方法直接生成Azure的SAS URL,但Label Studio预期的是内部预签路由(/tasks/xxx/presign/),而非直接返回云存储的HTTP地址。需要调整逻辑,构造符合平台要求的内部预签路径。
  • Azure Data Lake的HTTP URI支持:服务主体认证模式下,Azure Data Lake Storage Gen2完全支持生成带SAS令牌的HTTP可访问URL,技术上不存在障碍,问题出在代码的路由适配逻辑上。
  • 修正resolve_uri方法:当启用预签且存在任务对象时,应生成Label Studio的内部预签地址,而非直接返回Azure的SAS URL。示例修改如下:
elif isinstance(uri, str):
    try:
        if self.presign and task is not None:
            # 构造Label Studio内部预签路由
            from django.urls import reverse
            presign_path = reverse('tasks:presign', kwargs={'task_id': task.id})
            # 对原始URI进行URL编码
            import urllib.parse
            encoded_uri = urllib.parse.quote(uri)
            # 返回符合预期格式的预签地址
            return f"{presign_path}?fileuri={encoded_uri}"
        else:
            # 非预签场景直接返回Azure的HTTP URL
            http_url = self.generate_http_url(uri)
            return http_url
    except Exception:
        logger.info(f"Can't resolve URI={uri}", exc_info=True)
  • 测试规则验证:确保测试用例中的正则表达式能匹配新生成的预签地址,若路径有调整需同步更新!re_match的匹配规则。

内容的提问来源于stack exchange,提问作者Manrique Vargas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 17:53:15