跳转到内容

文件与集合

管理文件

Files API 提供了一套完整的文件管理操作。如果你的文件是公开可访问的,你可以在聊天对话中直接通过 URL 引用它们 — 请参阅 附加文件。对于非公开可访问的文件,请使用以下描述的方法之一进行上传。

你也可以从 xAI 控制台的 文件页面 查看和管理你已上传的所有文件。

上传文件

你可以通过多种方式上传文件:从文件路径、原始字节、BytesIO 对象或打开的文件句柄。

从文件路径上传

python
import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# Upload a file from disk
file = client.files.upload("/path/to/your/document.pdf")

print(f"File ID: {file.id}")
print(f"Filename: {file.filename}")
print(f"Size: {file.size} bytes")
print(f"Created at: {file.created_at}")
python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("XAI_API_KEY"),
    base_url="https://api.x.ai/v1",
)

# Upload a file
with open("/path/to/your/document.pdf", "rb") as f:
    file = client.files.create(
        file=f,
        purpose="assistants"
    )

print(f"File ID: {file.id}")
print(f"Filename: {file.filename}")
python
import os
import requests

url = "https://api.x.ai/v1/files"
headers = {
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}

with open("/path/to/your/document.pdf", "rb") as f:
    files = {"file": f}
    data = {"purpose": "assistants"}
    response = requests.post(url, headers=headers, files=files, data=data)

file_data = response.json()
print(f"File ID: {file_data['id']}")
print(f"Filename: {file_data['filename']}")
javascript
import OpenAI from "openai";
import fs from "fs";

const client = new OpenAI({
    apiKey: process.env.XAI_API_KEY,
    baseURL: "https://api.x.ai/v1",
});

// Upload a file
const file = await client.files.create({
    file: fs.createReadStream("/path/to/your/document.pdf"),
    purpose: "assistants",
});

console.log("File ID: " + file.id);
console.log("Filename: " + file.filename);
javascript
import fs from "fs";

const formData = new FormData();
formData.append("file", new Blob([fs.readFileSync("/path/to/your/document.pdf")]), "document.pdf");
formData.append("purpose", "assistants");

const response = await fetch("https://api.x.ai/v1/files", {
  method: "POST",
  headers: { Authorization: \`Bearer \${process.env.XAI_API_KEY}\` },
  body: formData,
});

const file = await response.json();
console.log("File ID: " + file.id);
console.log("Filename: " + file.filename);
bash
curl https://api.x.ai/v1/files \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -F file=@/path/to/your/document.pdf \\
  -F purpose=assistants

从字节上传

python
import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# Upload file content directly from bytes
content = b"This is my document content.\\nIt can span multiple lines."
file = client.files.upload(content, filename="document.txt")

print(f"File ID: {file.id}")
print(f"Filename: {file.filename}")

从文件对象上传

python
import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# Upload a file directly from disk
file = client.files.upload(open("document.pdf", "rb"), filename="document.pdf")

print(f"File ID: {file.id}")
print(f"Filename: {file.filename}")

带过期时间(TTL)上传

文件默认为永久存储,直到你删除它们。要使平台在固定时间窗口后自动删除文件,请在上传时设置 expires_after。这对于短期附件、临时会话数据和合规窗口很有用。

工作原理

expires_after 以秒为单位设置,从上传时间开始计算。它必须在 3600(1小时)和 2592000(30天)之间,包括这两个值。省略此字段可使文件永久保存。

响应中包含 expires_at,即文件将被删除的绝对 UTC 时间戳。一旦该时间过去,文件就会消失:它不再出现在列表响应中,获取其元数据或内容会返回 not found,并且无法再在聊天附件中通过 id 引用。

你也可以在 TTL 过期前的任何时间手动删除文件。

WARNING

多部分字段顺序很重要expires_after 必须在多部分正文中出现在 file 字段之前。在 file 之后发送 expires_after 的请求将被 400 拒绝。

python
import os
from datetime import timedelta
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# Upload a file that will be auto-deleted in 24 hours.
# expires_after accepts an int (seconds) or a datetime.timedelta.
file = client.files.upload(
    "/path/to/document.pdf",
    expires_after=timedelta(hours=24),
)

print(f"File ID: {file.id}")
print(f"Expires at: {file.expires_at.ToDatetime()}")
python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("XAI_API_KEY"),
    base_url="https://api.x.ai/v1",
)

# expires_after follows the OpenAI shape: an object anchored at "created_at".
with open("/path/to/document.pdf", "rb") as f:
    file = client.files.create(
        file=f,
        purpose="assistants",
        expires_after={"anchor": "created_at", "seconds": 86400},  # 24 hours
    )

print(f"File ID: {file.id}")
print(f"Expires at: {file.expires_at}")  # Unix seconds, 24h from now
python
import os
import requests

url = "https://api.x.ai/v1/files"
headers = {
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}

# expires_after MUST appear before file in the multipart body — see the note below.
with open("/path/to/document.pdf", "rb") as f:
    response = requests.post(
        url,
        headers=headers,
        data=[
            ("expires_after", "86400"),  # 24 hours in seconds
            ("purpose", "assistants"),
        ],
        files={"file": f},
    )

file_data = response.json()
print(f"File ID: {file_data['id']}")
print(f"Expires at: {file_data['expires_at']}")
javascript
import OpenAI from "openai";
import fs from "fs";

const client = new OpenAI({
    apiKey: process.env.XAI_API_KEY,
    baseURL: "https://api.x.ai/v1",
});

const file = await client.files.create({
    file: fs.createReadStream("/path/to/document.pdf"),
    purpose: "assistants",
    expires_after: { anchor: "created_at", seconds: 86400 },  // 24 hours
});

console.log("File ID: " + file.id);
console.log("Expires at: " + file.expires_at);
javascript
import fs from "fs";

const formData = new FormData();
// expires_after MUST be appended before the file field.
formData.append("expires_after", "86400");  // 24 hours in seconds
formData.append("purpose", "assistants");
formData.append(
  "file",
  new Blob([fs.readFileSync("/path/to/document.pdf")]),
  "document.pdf",
);

const response = await fetch("https://api.x.ai/v1/files", {
  method: "POST",
  headers: { Authorization: \`Bearer \${process.env.XAI_API_KEY}\` },
  body: formData,
});

const file = await response.json();
console.log("File ID: " + file.id);
console.log("Expires at: " + file.expires_at);
bash
# -F fields are sent in declaration order.
# expires_after must come before file in the form body.
curl https://api.x.ai/v1/files \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -F expires_after=86400 \\
  -F purpose=assistants \\
  -F file=@/path/to/document.pdf

带进度跟踪的上传

使用回调或进度条跟踪大文件的上传进度。

python
import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# Define a custom progress callback
def progress_callback(bytes_uploaded: int, total_bytes: int):
    percentage = (bytes_uploaded / total_bytes) * 100 if total_bytes else 0
    mb_uploaded = bytes_uploaded / (1024 * 1024)
    mb_total = total_bytes / (1024 * 1024)
    print(f"Progress: {mb_uploaded:.2f}/{mb_total:.2f} MB ({percentage:.1f}%)")

# Upload with progress tracking
file = client.files.upload(
    "/path/to/large-file.pdf",
    on_progress=progress_callback
)

print(f"Successfully uploaded: {file.filename}")

列出文件

获取你已上传文件的列表,支持分页和排序选项。

可用选项

  • limit:返回的最大文件数。如果未指定,则使用服务器默认值 100。最大值为 100。
  • order:排序顺序。可以是 "asc"(升序)或 "desc"(降序)。默认为 "desc"
  • sort_by:排序字段。选项:"created_at""filename""size"。默认为 "created_at"
  • pagination_token:传递上一个响应返回的 pagination_token 以获取下一页。第一页省略此参数。

响应始终包含 pagination_token。当返回的页面长度小于 limit 时,表示已到达列表末尾。

python
import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# List files with pagination and sorting
response = client.files.list(
    limit=10,
    order="desc",
    sort_by="created_at"
)

for file in response.data:
    expires = file.expires_at.ToDatetime() if file.HasField("expires_at") else "never"
    print(f"File: {file.filename} (ID: {file.id}, Size: {file.size} bytes, Expires: {expires})")
python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("XAI_API_KEY"),
    base_url="https://api.x.ai/v1",
)

# List files
files = client.files.list()

for file in files.data:
    print(f"File: {file.filename} (ID: {file.id})")
python
import os
import requests

url = "https://api.x.ai/v1/files"
headers = {
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}

response = requests.get(url, headers=headers)
files = response.json()

for file in files.get("data", []):
    print(f"File: {file['filename']} (ID: {file['id']})")
javascript
import OpenAI from "openai";

const client = new OpenAI({
    apiKey: process.env.XAI_API_KEY,
    baseURL: "https://api.x.ai/v1",
});

// List files
const files = await client.files.list();

for (const file of files.data) {
    console.log(\`File: \${file.filename} (ID: \${file.id})\`);
}
javascript
const response = await fetch("https://api.x.ai/v1/files", {
  headers: { Authorization: \`Bearer \${process.env.XAI_API_KEY}\` },
});

const files = await response.json();

for (const file of files.data) {
  console.log(\`File: \${file.filename} (ID: \${file.id})\`);
}
bash
curl https://api.x.ai/v1/files \\
  -H "Authorization: Bearer $XAI_API_KEY"

遍历所有文件

List 端点每次调用最多返回 limit 个文件(上限为 100)。要枚举所有文件,请持续使用上一个响应中的 pagination_token 调用端点,直到响应返回的项目数少于 limit

python
import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# Walk every page until the API returns a short page.
page_size = 100
token = None
all_files = []

while True:
    response = client.files.list(
        limit=page_size,
        order="desc",
        sort_by="created_at",
        pagination_token=token,
    )
    all_files.extend(response.data)
    if len(response.data) < page_size:
        break
    token = response.pagination_token

print(f"Total files: {len(all_files)}")
python
import os
import requests

url = "https://api.x.ai/v1/files"
headers = {"Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"}

page_size = 100
params = {"limit": page_size, "order": "desc", "sort_by": "created_at"}
all_files = []

while True:
    response = requests.get(url, headers=headers, params=params).json()
    all_files.extend(response.get("data", []))
    if len(response.get("data", [])) < page_size:
        break
    params["pagination_token"] = response["pagination_token"]

print(f"Total files: {len(all_files)}")
javascript
const pageSize = 100;
const baseParams = { limit: String(pageSize), order: "desc", sort_by: "created_at" };
const allFiles = [];
let token;

while (true) {
  const params = new URLSearchParams({ ...baseParams, ...(token ? { pagination_token: token } : {}) });
  const response = await fetch(\`https://api.x.ai/v1/files?\${params}\`, {
    headers: { Authorization: \`Bearer \${process.env.XAI_API_KEY}\` },
  });
  const page = await response.json();
  allFiles.push(...page.data);
  if (page.data.length < pageSize) break;
  token = page.pagination_token;
}

console.log(\`Total files: \${allFiles.length}\`);

获取文件元数据

获取特定文件的详细信息。

python
import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# Get file metadata by ID
file = client.files.get("file-abc123")

print(f"Filename: {file.filename}")
print(f"Size: {file.size} bytes")
print(f"Created: {file.created_at}")
# expires_at is only set when the file was uploaded with expires_after
if file.HasField("expires_at"):
    print(f"Expires at: {file.expires_at.ToDatetime()}")
python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("XAI_API_KEY"),
    base_url="https://api.x.ai/v1",
)

# Get file metadata
file = client.files.retrieve("file-abc123")

print(f"Filename: {file.filename}")
print(f"Size: {file.bytes} bytes")
# Unix seconds, or None if the file does not expire.
print(f"Expires at: {file.expires_at}")
python
import os
import requests

file_id = "file-abc123"
url = f"https://api.x.ai/v1/files/{file_id}"
headers = {
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}

response = requests.get(url, headers=headers)
file = response.json()

print(f"Filename: {file['filename']}")
print(f"Size: {file['bytes']} bytes")
javascript
import OpenAI from "openai";

const client = new OpenAI({
    apiKey: process.env.XAI_API_KEY,
    baseURL: "https://api.x.ai/v1",
});

// Get file metadata
const file = await client.files.retrieve("file-abc123");

console.log("Filename: " + file.filename);
console.log("Size: " + file.bytes + " bytes");
javascript
const response = await fetch("https://api.x.ai/v1/files/file-abc123", {
  headers: { Authorization: \`Bearer \${process.env.XAI_API_KEY}\` },
});

const file = await response.json();
console.log("Filename: " + file.filename);
console.log("Size: " + file.bytes + " bytes");
bash
curl https://api.x.ai/v1/files/file-abc123 \\
  -H "Authorization: Bearer $XAI_API_KEY"

获取文件内容

下载已上传文件的原始字节。该端点流式传输响应,因此它可以处理任何支持大小的文件,而无需在 API 层将整个负载缓冲在内存中。

python
import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# Returns the complete file content as bytes.
content = client.files.content("file-abc123")

# Save to disk
with open("downloaded.pdf", "wb") as f:
    f.write(content)

print(f"Saved {len(content)} bytes")
python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("XAI_API_KEY"),
    base_url="https://api.x.ai/v1",
)

# Stream content straight to disk
client.files.content("file-abc123").write_to_file("downloaded.pdf")
python
import os
import requests

file_id = "file-abc123"
url = f"https://api.x.ai/v1/files/{file_id}/content"
headers = {"Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"}

# Stream to disk so large files don't sit in memory
with requests.get(url, headers=headers, stream=True) as response:
    response.raise_for_status()
    with open("downloaded.pdf", "wb") as f:
        for chunk in response.iter_content(chunk_size=1024 * 1024):
            f.write(chunk)
javascript
import OpenAI from "openai";
import fs from "fs";

const client = new OpenAI({
    apiKey: process.env.XAI_API_KEY,
    baseURL: "https://api.x.ai/v1",
});

const response = await client.files.content("file-abc123");
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync("downloaded.pdf", buffer);
javascript
import fs from "fs";

const response = await fetch("https://api.x.ai/v1/files/file-abc123/content", {
  headers: { Authorization: \`Bearer \${process.env.XAI_API_KEY}\` },
});

const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync("downloaded.pdf", buffer);
bash
curl https://api.x.ai/v1/files/file-abc123/content \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  --output downloaded.pdf

删除文件

当文件不再需要时,将其删除。

python
import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))

# Delete a file
delete_response = client.files.delete("file-abc123")

print(f"Deleted: {delete_response.deleted}")
print(f"File ID: {delete_response.id}")
python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("XAI_API_KEY"),
    base_url="https://api.x.ai/v1",
)

# Delete a file
delete_response = client.files.delete("file-abc123")

print(f"Deleted: {delete_response.deleted}")
print(f"File ID: {delete_response.id}")
python
import os
import requests

file_id = "file-abc123"
url = f"https://api.x.ai/v1/files/{file_id}"
headers = {
    "Authorization": f"Bearer {os.getenv('XAI_API_KEY')}"
}

response = requests.delete(url, headers=headers)
result = response.json()

print(f"Deleted: {result['deleted']}")
print(f"File ID: {result['id']}")
javascript
import OpenAI from "openai";

const client = new OpenAI({
    apiKey: process.env.XAI_API_KEY,
    baseURL: "https://api.x.ai/v1",
});

// Delete a file
const deleteResponse = await client.files.delete("file-abc123");

console.log("Deleted: " + deleteResponse.deleted);
console.log("File ID: " + deleteResponse.id);
javascript
const response = await fetch("https://api.x.ai/v1/files/file-abc123", {
  method: "DELETE",
  headers: { Authorization: \`Bearer \${process.env.XAI_API_KEY}\` },
});

const result = await response.json();
console.log("Deleted: " + result.deleted);
console.log("File ID: " + result.id);
bash
curl -X DELETE https://api.x.ai/v1/files/file-abc123 \\
  -H "Authorization: Bearer $XAI_API_KEY"

文件对象

所有返回元数据的 Files API 端点(上传、列表、获取元数据)都返回相同的 file 对象结构:

字段类型描述
idstring唯一文件标识符(例如 file_a128090d-f0c9-4873-bd84-e499777e7417)。在任何需要 file_id 的地方使用它,包括聊天附件。
filenamestring上传时提供的原始文件名。
bytesinteger文件大小,以字节为单位。
created_atinteger上传时间,为 Unix 时间戳(秒)。
expires_atinteger 或 null文件将被删除的 Unix 时间戳。永久文件为 null;当文件使用 expires_after 上传时设置。
objectstring始终为 "file"。为 OpenAI 兼容性而返回。
purposestring回显上传时发送的 purpose 值。xAI 不强制执行或解释此字段;为 OpenAI SDK 兼容性而存储。设置为 "assistants" 是常规选择。

限制与注意事项

文件大小限制

  • 最大文件大小:每个文件 48 MB
  • 处理时间:较大的文件可能需要更长的处理时间

文件保留

  • 清理:不再需要时删除文件以管理存储
  • 访问:文件范围限定在你的团队/组织内

支持的格式

虽然支持许多基于文本的格式,但系统在以下格式上表现最佳:

  • 结构化文档(有清晰的章节、标题)
  • 纯文本和 Markdown
  • 具有清晰信息层次结构的文档

支持的文件类型包括:

  • 纯文本文件 (.txt)
  • Markdown 文件 (.md)
  • 代码文件 (.py, .js, .java 等)
  • CSV 文件 (.csv)
  • JSON 文件 (.json)
  • PDF 文档 (.pdf)
  • 以及许多其他基于文本的格式

下一步

本文档为 docs.x.ai 全站中文翻译,由 AI 自动翻译生成。代码示例请以原文为准。