mcpField
F
fileset-api

fileset-api

github.com/stahura开发24170 次安装26 周前更新
代码仓库

关于 fileset-api

fileset-api 是面向 Domo 自定义应用开发者的 FileSets 测试版 API 指南。它介绍如何通过 Domo 文件 API 操作文件、管理容器,并对文件内容执行语义查询。

主要功能

  1. 01上传和下载文件
  2. 02浏览、搜索并分页列出文件
  3. 03读取文件元数据并删除文件
  4. 04创建和搜索 FileSets
  5. 05用自然语言查询文件内容

适用场景

  1. 01在 Domo 自定义应用中构建文件浏览器
  2. 02将生成的 CSV 文件上传到 FileSet
  3. 03按目录或名称查找文件
  4. 04用自然语言查询报告内容

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/stahura/domo-ai-vibe-rules --skill fileset-api

安装后在 Claude Code 中输入/fileset-api确认已加载。

详细介绍

Domo FileSets — App Framework API

状态: 此 API 处于 BETA 阶段,可能会发生变更。请采取防御性编程方式——使用 try/catch 包装调用,并向用户显示有意义的错误信息。

FileSets 是 Domo 的文件存储系统。在自定义应用中,你可以上传和下载文件、浏览目录树、按名称搜索,以及针对文件内容运行 AI 驱动的语义查询。

设置 — 无需配置清单

与数据集不同,fileset 不需要在 manifest.json 中添加条目。只需在服务文件中将 fileset ID 定义为常量:

// src/services/api.js
const FILESET_ID = 'b6ebf7e9-64ae-4e6d-b8ca-b356fe62923f'; // replace with your fileset ID

可从 Domo UI 获取 fileset ID,也可通过 fileset-cli 技能获取(filesets search --name "...")。


URL 模式:/api/ 与 /domo/

在 Domo 自定义应用中,有两种有效的方式:

模式适用场景
fetch('/api/files/v1/...')最简单。适用于所有 JSON 和二进制调用。无需导入。
domo.get('/domo/files/v1/...')需要使用 domo.js 代理时使用(例如已在其他位置使用 domo.*)。仅支持 JSON,不支持二进制。

以下示例使用 fetch('/api/...'),因为它可以一致地处理 JSON 和二进制(上传/下载)。无论如何,二进制操作都必须使用 fetch。


文件

列出 fileset 中的文件
const response = await fetch(`/api/files/v1/filesets/${FILESET_ID}/files/search`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    fieldSort: [{ field: 'created', order: 'DESC' }],
    filters: [],
    dateFilters: []
  })
});
const data = await response.json();
const files = data.files; // array of file objects

按目录和名称筛选:

const response = await fetch(
  `/api/files/v1/filesets/${FILESET_ID}/files/search` +
  `?directoryPath=/reports&immediateChildren=true&limit=50`,
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      fieldSort: [{ field: 'name', order: 'ASC' }],
      filters: [{ field: 'name', value: ['.pdf'], operator: 'LIKE' }],
      dateFilters: []
    })
  }
);

使用 data.pageContext.next 中的 next 令牌进行分页:

// data.pageContext shape: { next, offset, limit, total }
if (data.pageContext.next) {
  const nextPage = await fetch(
    `/api/files/v1/filesets/${FILESET_ID}/files/search?next=${data.pageContext.next}`,
    { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) }
  );
}
获取文件元数据
// By file ID
const response = await fetch(`/api/files/v1/filesets/${FILESET_ID}/files/${fileId}`);
const file = await response.json();
// { id, path, name, fileType, contentType, size, hash, created, createdBy }

// By path (when you know the directory structure)
const response = await fetch(
  `/api/files/v1/filesets/${FILESET_ID}/path?path=${encodeURIComponent('/reports/march.pdf')}`
);
下载文件

使用 fetch 并创建临时下载链接。下载端点会返回二进制内容:

async function downloadFile(fileId, filename) {
  const response = await fetch(
    `/api/files/v1/filesets/${FILESET_ID}/files/${fileId}/download`
  );
  if (!response.ok) throw new Error(`Download failed: ${response.status}`);

  const blob = await response.blob();
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

对于基于文本的文件,也可以使用 .text() 而不是 .blob(),直接读取内容:

const response = await fetch(`/api/files/v1/filesets/${FILESET_ID}/files/${fileId}/download`);
const text = await response.text(); // use for .txt, .csv, .md, etc.
上传文件

使用包含两个部分的 FormData——二进制文件和目录元数据。不要设置 Content-Type;浏览器会自动使用正确的 multipart 边界:

async function uploadFile(file, directoryPath = '/') {
  const formData = new FormData();
  formData.append('file', file);                                           // File or Blob
  formData.append('createFileRequest', JSON.stringify({ directoryPath })); // metadata

  const response = await fetch(`/api/files/v1/filesets/${FILESET_ID}/files`, {
    method: 'POST',
    body: formData
    // ⚠️ Do NOT set Content-Type header — browser handles it
  });

  if (!response.ok) throw new Error(`Upload failed: ${response.status}`);
  return response.json(); // returns the new file object
}

从文件输入元素上传:

document.getElementById('file-input').addEventListener('change', async (e) => {
  const file = e.target.files[0];
  const record = await uploadFile(file, '/uploads/2024');
  console.log('Uploaded:', record.id, record.path);
});

从生成的 Blob 上传(例如 CSV 导出):

const csv = 'name,value\nAlice,100\nBob,200';
const blob = new Blob([csv], { type: 'text/csv' });
const file = new File([blob], 'export.csv', { type: 'text/csv' });
await uploadFile(file, '/exports');
删除文件
// By file ID
await fetch(`/api/files/v1/filesets/${FILESET_ID}/files/${fileId}`, { method: 'DELETE' });

// By path
await fetch(
  `/api/files/v1/filesets/${FILESET_ID}/path?path=${encodeURIComponent('/reports/march.pdf')}`,
  { method: 'DELETE' }
);

FileSets(容器)

你可以在应用中创建和管理 fileset 容器,不过通常 fileset 已经存在,应用只需使用硬编码的 ID。

搜索 fileset
const response = await fetch('/api/files/v1/filesets/search?limit=50', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    fieldSort: [{ field: 'updated', order: 'DESC' }],
    filters: [{ field: 'name', value: ['reports'], operator: 'LIKE' }],
    dateFilters: []
  })
});
创建 fileset
const response = await fetch('/api/files/v1/filesets', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Monthly Reports', description: 'Automated PDF outputs' })
});
const fileset = await response.json();
const filesetId = fileset.id;

AI 驱动的文件查询

需要在 fileset 上启用 aiEnabled: true。此功能会针对文件内容运行自然语言问题,并返回带有相关性评分的排序结果:

const response = await fetch(`/api/files/v1/filesets/${FILESET_ID}/query`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    query: 'What were the key revenue drivers last quarter?',
    directoryPath: '/reports/2024',
    topK: 5
  })
});
const data = await response.json();
// data.matches: [{ id, node: { file object }, score: 0.89 }, ...]

文件对象结构

{
  "id": "xyz789-file-id",
  "path": "/reports/2024/march.pdf",
  "name": "march.pdf",
  "fileType": "PDF",
  "contentType": "application/pdf",
  "size": 204800,
  "hash": "sha256:abc...",
  "hashAlgorithm": "SHA256",
  "created": "2024-03-01T08:00:00Z",
  "createdBy": 12345
}

完整示例:文件浏览器服务

适用于 React 应用的简洁服务模块模式:

// src/services/filesetApi.js

const FILESET_ID = 'your-fileset-id-here';
const BASE = `/api/files/v1/filesets/${FILESET_ID}`;

export async function listFiles(directoryPath = null, nameFilter = null) {
  const params = new URLSearchParams({ limit: '100' });
  if (directoryPath) params.set('directoryPath', directoryPath);

  const filters = nameFilter
    ? [{ field: 'name', value: [nameFilter], operator: 'LIKE' }]
    : [];

  const response = await fetch(`${BASE}/files/search?${params}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ fieldSort: [{ field: 'name', order: 'ASC' }], filters, dateFilters: [] })
  });
  if (!response.ok) throw new Error(`List failed: ${response.status}`);
  const data = await response.json();
  return data.files ?? [];
}

export async function downloadFileContent(fileId) {
  const response = await fetch(`${BASE}/files/${fileId}/download`);
  if (!response.ok) throw new Error(`Download failed: ${response.status}`);
  return response.text(); // swap for .blob() for binary files
}

export async function uploadFile(file, directoryPath = '/') {
  const form = new FormData();
  form.append('file', file);
  form.append('createFileRequest', JSON.stringify({ directoryPath }));
  const response = await fetch(`${BASE}/files`, { method: 'POST', body: form });
  if (!response.ok) throw new Error(`Upload failed: ${response.status}`);
  return response.json();
}

export async function queryFiles(question, directoryPath = null, topK = 5) {
  const body = { query: question, topK };
  if (directoryPath) body.directoryPath = directoryPath;
  const response = await fetch(`${BASE}/query`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body)
  });
  if (!response.ok) throw new Error(`Query failed: ${response.status}`);
  const data = await response.json();
  return data.matches ?? [];
}

通过 CLI 管理 fileset

若要发现 fileset ID、浏览文件、将文件下载到磁盘,或在应用外运行命令,请使用 fileset-cli 技能。

评论

支持 Markdown