关于生成文件下载链接使用方式的重要更新

尊敬的 Tripo 用户:

我们在此通知您,平台资源访问和使用方式即将发生一项变更。

变更内容是什么?

2025 年 4 月 9 日起,我们将对所有生成的资源 URL 强制执行 CORS 策略。这意味着我们平台上的所有资源都将需要对跨域请求进行适当处理,换句话说,您不能直接使用 Tripo API 返回的链接来提供生成的模型文件。

为什么要实施此变更?

此项变更旨在加强我们对提高安全性防止未经授权跨源访问资源的承诺。CORS(跨域资源共享)是一种机制,允许服务器指定哪些外部域可以访问资源。
有关 CORS 的更多信息,您可以参考 MDN 的指南

对您工作流程的影响

目前,我们不为资源 URL 提供 CORS 头部。因此,如果您在浏览器中或从外部域直接使用或链接这些资源,您可能会遇到问题。
为确保继续访问这些资产,您需要采取以下措施之一:

  1. 下载并将资源本地保存:您可以下载资源并将其存储在您的后端。一旦本地保存,您就可以从您的服务器提供这些资产,而无需 CORS 限制。
  2. 使用边缘代理(例如 Next.js API 路由、Cloudflare Workers):您可以使用边缘代理来获取和提供资源,同时向响应添加必要的 CORS 头部。例如:
    • Next.js API 路由:设置 API 路由以从我们的平台获取资源,并使用适当的 CORS 头部转发它们。
    • Cloudflare Workers:使用 Cloudflare Workers 在从您的服务器提供我们的资产时添加 CORS 头部。

关键日期:

强制执行将于 2025 年 4 月 9 日开始。

如何准备:

  • 审查您的集成:确保您的系统能够处理资源 URL 的 CORS。
  • 下载并保存资源:如果您不使用边缘代理,请考虑下载并将资源存储在您的后端。
  • 设置边缘代理:如果您使用 Next.js 或 Cloudflare Workers 等解决方案,请更新您的配置,确保资产以适当的 CORS 头部提供。
  • 测试您的系统:验证所有对我们平台的跨域请求都按预期工作。

需要实际的代码示例吗? 如果您不确定如何开始或觉得实施过程困难,我们提供了实用的代码片段来帮助您入门。请参阅附录了解更多详情。

常见问题

  • 我生成的文件丢失了吗?

    没有。 您可以随时从 API 中检索新的 URL。

  • 我没有直接返回您的 URL,但我进行了一些后处理。我应该担心吗?

    如果您没有直接将我们的 URL 返回给您的用户,您可以跳过此变更。但是,我们建议您监控您的使用情况,特别是如果您发现系统中出现任何错误峰值或异常行为。

需要帮助?

我们理解此项变更可能需要您更新工作流程。如果您在设置边缘代理方面需要任何帮助,或对此过渡有任何疑问,请通过 support@tripo3d.ai 联系我们的支持团队。
感谢您的合作,我们将努力提升我们平台的安全性!祝您安全高效!
此致,
Tripo 团队

附录 A:后端重新保存方法

如果您正在使用 FastAPI(易于移植或转换为任何其他框架或语言),以下是您可以如何调整现有代码以处理 CORS 并将资源本地保存的方法:

当前代码:

@app.post("/")
def generate(prompt: str) -> str:
    resp = ...  # API works
    return resp.json()['url']

您可以轻松修改为:

import httpx
import uuid
import os

from fastapi.responses import FileResponse
from fastapi import HTTPException

@app.post("/")
def generate(prompt: str) -> str:
    resp = ...  # same as above

    # Add the code below
    file_id = str(uuid.uuid4())
    # 确保下载目录存在
    os.makedirs("./downloaded", exist_ok=True)
    with httpx.Client() as client:
        # Download the artifact
        response = client.get(resp.json()['url']) # Use resp.json()['url'] for the actual URL

        # Check if the request was successful
        if response.status_code == 200:
            # Then resave it
            with open(f"./downloaded/{file_id}.glb", "wb") as file:
                file.write(response.content)

    return file_id

@app.get("/artifact/{file_id}")
def download(file_id: str) -> FileResponse:
    if os.path.exists(f"./downloaded/{file_id}.glb"):
      return FileResponse(f"./downloaded/{file_id}.glb")
    raise HTTPException(status_code=404, detail="Item not found")

下载并本地保存文件后,您应该使用新的 URL 为您的用户提供服务。例如,如果您的应用程序托管在 https://app.example.com,您应该提供的 URL 将如下所示:

https://app.example.com/artifact/<file_id>

此代码片段仅演示如何调整您的集成。但是,您应该考虑一些重要事项:

  • 添加适当的身份验证:确保下载链接受到适当的身份验证方法的保护,以防止未经授权的访问。
  • 使用可靠的存储:建议将文件保存到更可靠的存储解决方案,例如专用服务器或 S3 存储桶等云存储选项。
  • 存储元数据:在您的数据库或其他存储系统中保留资源元数据记录以供将来使用(例如跟踪或审计)。

附录 B:边缘代理方法

如果您正在开发单页应用程序 (SPA)前端后端 (BFF) 服务器,并且不希望直接在服务器上处理文件下载和存储,您可以使用边缘代理方法。这允许您从我们的服务器获取文件,应用必要的 CORS 头部,然后将其提供给您的用户。

解决方案 1:使用边缘函数下载并重新发送文件

以下是使用 Cloudflare Workers 实施此方法的示例。此解决方案将通过下载文件并在您的域下重新发送来处理 CORS 问题。

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  // Parse the request URL
  const url = new URL(request.url);

  // Get the target URL from the 'url' query parameter
  const targetUrl = url.searchParams.get('url');

  // If no URL is provided, return an error
  if (!targetUrl) {
    return new Response('Please provide a URL parameter', {
      status: 400,
      headers: {
        'Content-Type': 'text/plain',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type'
      }
    });
  }

  // Handle preflight OPTIONS request
  if (request.method === 'OPTIONS') {
    return handleCORS();
  }

  try {
    // Fetch the file from the target URL
    const response = await fetch(targetUrl);

    // If the fetch failed, return the error
    if (!response.ok) {
      return new Response(`Failed to fetch from target URL: ${response.statusText}`, {
        status: response.status,
        headers: corsHeaders()
      });
    }

    // Get the content type from the response or default to octet-stream
    const contentType = response.headers.get('Content-Type') || 'application/octet-stream';

    // Get the content disposition or create one from the URL
    let contentDisposition = response.headers.get('Content-Disposition');
    if (!contentDisposition) {
      // Extract filename from the URL
      const fileName = targetUrl.split('/').pop().split('?')[0] || 'file';
      contentDisposition = `attachment; filename="${fileName}"`;
    }

    // Create a new response with CORS headers
    const newResponse = new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: {
        'Content-Type': contentType,
        'Content-Disposition': contentDisposition,
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type',
        'Cache-Control': 'public, max-age=3600' // Cache for 1 hour
      }
    });

    return newResponse;
  } catch (error) {
    return new Response(`Error fetching the file: ${error.message}`, {
      status: 500,
      headers: corsHeaders()
    });
  }
}

// Handle CORS preflight requests
function handleCORS() {
  return new Response(null, {
    status: 204, // No content
    headers: corsHeaders()
  });
}

// Create CORS headers object
function corsHeaders() {
  return {
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': 'GET, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type',
    'Access-Control-Max-Age': '86400' // 24 hours
  };
}

一旦您的 Cloudflare Worker 设置完毕,您就可以通过以下 JavaScript 代码将其集成到您的 SPA 中以获取文件:

fetch('https://your-worker-url.workers.dev/?url=<target_url>')
  .then(response => response.blob())
  .then(blob => {
    // Create a download link
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'downloaded-file.pdf';
    document.body.appendChild(a);
    a.click();
    a.remove();
  })
  .catch(error => console.error('Error:', error));

此解决方案非常适合需要绕过 CORS 限制并将文件下载并提供给最终用户的 SPA 或 BFF 服务器。文件从目标 URL 获取,通过边缘代理,并以必要的 CORS 头部提供。

解决方案 2:设置 CORS 头部代理

如果您更喜欢设置一个简单的 CORS 代理,您可以参考 Cloudflare 提供的此示例:Cloudflare Workers - CORS Header Proxy
这将使您能够更轻松地处理跨域请求,同时仍遵守 CORS 策略。

重要注意事项:

  • 身份验证:确保使用身份验证方法(例如,API 密钥、OAuth 等)正确保护您的边缘函数,以防止未经授权访问您的文件。
  • 存储:虽然此方法可行,但我们仍然建议将资源保存在您的服务器上以供将来使用,特别是当您需要管理大规模下载或确保对资源的可靠访问时。

Advancing 3D generation to new heights

moving at the speed of creativity, achieving the depths of imagination.