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

尊敬的 Tripo 用户:

我们写此信是为了告知您即将发生的一项变更,该变更可能会影响您从我们平台访问和使用资源的方式。

正在发生什么变化?

我们将对所有生成的文件 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 头。

如何准备:

  • 检查您的集成:确保您的系统能够处理文件 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 # Import os module

from fastapi.responses import FileResponse
from fastapi import HTTPException

@app.post("/")
def generate(prompt: str) -> str:
    resp = ...  # same as above
    url = resp.json()['url'] # Assuming 'url' is extracted from resp.json()

    # Add the code below
    file_id = str(uuid.uuid4())
    # Ensure the directory exists
    os.makedirs("./downloaded", exist_ok=True)
    with httpx.Client() as client:
        # Download the artifact
        response = client.get(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)
        else:
            raise HTTPException(status_code=response.status_code, detail="Failed to download artifact")

    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.