# @filefreak\.io/sdk 中文文档

规范地址：https://npmcn.com/package/%40filefreak.io/sdk/

版本：0\.20\.0
npm 元数据更新时间：2026-11-10T19:25:43.553Z
中文译文更新时间：2026-11-14T17:48:32.565Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40filefreak.io/sdk
原文对照：https://npmcn.com/package/%40filefreak.io/sdk/?lang=original
项目主页：https://filefreak.io/developers/reference

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：632 kB，48 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=20
- 运行依赖：0 个
- 首次发布：2026-10-25T17:33:46.636Z
- 最新版本发布：2026-11-10T19:25:43.347Z
- 近 30 天下载量：4374（2026-10-15 至 2026-11-13，npm 官方下载统计）
- 已发布版本数：23（近 12 个月 23 个）

## 中文简介

FileFreak的开发者API用于节点和浏览器:每个端点,直接上传到部分存储,下载范围,以及接下来的更改.

## 安装

```sh
npm install @filefreak.io/sdk
```

也可以使用：`pnpm add @filefreak.io/sdk`、`yarn add @filefreak.io/sdk`、`bun add @filefreak.io/sdk`

## README

# @ filefreak.io/sdk (英语)

FileFreak 开发者 API,来自 TypeScript 或 JavaScript, 在节点 20 和 后入并入于浏览器. 无相依相.

每个端点都是函数,从相同的表格中键入 API 构建 从. 周围:直接上传至部分存储并继续进行 中断后, 一个大文件的新版本只发送什么 已更改, 下载到区域中, 并对照文件 SHA-256,列表和修改读取到尾端,被发送并读取的被Shard Protection下的文件被密封 通过他们的地图,共享链接所保存的没有密钥,并且请求仅在此时再次发出 无法使任何东西两次。 参考文献为: [https://filefreak.io/developers/参考文献 互联网档案馆的存檔,存档日期2014-12-22](https://filefreak.io/developers/reference)。 。 。 .

## 在服务器上

```ts
import { FileFreak } from "@filefreak.io/sdk";
import { fromPath, toPath } from "@filefreak.io/sdk/node";

const ff = new FileFreak({ apiKey: process.env.FILEFREAK_KEY });

const { item: folder } = await ff.folders.create({ name: "uploads", ifExists: "use" });
const file = await ff.upload(await fromPath("film.mp4"), {
  parentId: folder.id,
  onProgress: (sent, total) => console.log(`${Math.round((sent / total) * 100)}%`),
});

await ff.download(file.id, await toPath("copy.mp4"));
const bytes = await ff.bytes(file.id); // for a file small enough to hold in memory
```

`fromPath` 在发送时读取文件的一部分, 所以文件更大 比记忆还好. `toPath` 在文件旁边写并给出它的名字 只有每个字节存在一次:一个失败的下载会留下一无所有. 在Shard Protection下的文件没有地址 `download` 财务报告和审定财务报表 `bytes` 在地图上读一下,每个碎片都检查过了 一个 以粗体格式第2版所写,按其内容剪去的块表示: 读取方式相同,在获取任何块前检查其大纲. 进入Shard保护下的文件夹, `upload` 以 文件在发送前是自己的密钥, 所以文件中没有任何一个是普通的 存储。 键是用于上传的 API , 并且没有被保存到 上传一个询问,在发送任何文件之前,哪些片段储存.

保存在存储中的文件会在读取时重新组合,从 0.7.0 (英语). `download`, (中文(简体) ), `bytes` 财务报告和审定财务报表 `get` 问其地址 说他们可以, 取出每个地方作为地址,并充气 存储压缩, 每一个检查以给出精确的 API 版式 说它坚持。 不添加的文件被拒绝, 且没有保存 : `layout` 当布局本身没有的时候, `blob_size` 存储时 比它说, `place_damaged` 当一个地方不是储藏的 `place_unavailable` 当存储在多次尝试后不会给出.

上传到公共文件夹或取代公共文件的文件是 从未被压缩过,档案、图片、视频或 安装器(其中AppImage、msi或pkg)。 内容 `publicUrl` 给 它的字节,用于下载链接或 `<img>`。一个存储在压缩之前 它被公之于众 `packed: true`,以及 `publicUrl` 打开它的页面, 它在浏览器中重现: 再次上传到公众 用于提供字节的地址的文件夹.

在服务器上保留密钥 。 从网页发送的密钥被拒绝 .

## 每次下载都被检查

每一次上传都会从它发送的字节中找到它的SHA-256 记录在文件,从0.15.0, 无论是否 `sha256` 给出; 1 给定时与它相对应。 每次下载, `bytes` 财务报告和审定财务报表 `get` 开什么玩笑 写它和API给文件的 SHA-256 相比较,从来没有 一个从存储器读取,所以一个文件在存储器中或途中更改被捕获. 一个不匹配抛出 `IntegrityError` 其水槽被中止,所以 `toPath` 留下任何东西.

```ts
import { IntegrityError } from "@filefreak.io/sdk";

const got = await ff.download(file.id, await toPath("copy.mp4"));
got.verification; // { verified: true, by: "sha256", sha256: "1a2b..." }
```

`verification` 说如何检查: `by: "sha256"`· ; `by: "seals"` (单位:千美元) 在Shard 保护下的文件, 每件文件都要对照它的封条检查 当它到达时;或 `verified: false` 与 `reason: "no_checksum"` 用于文件 2026年11月前从网站发送的文件 对. `get` 给出它保存的每个文件 `verification` 属于自己的.

一个大文件作为数个范围同时取出,从中运出 秩序。 秩序。 所到之事,已随所至而散去;所取之事,已读回去 一旦每个字节被写成,就从水槽中报告 `onVerifying`该 需要水槽拥有 `read`,哪个 `toPath` 财务报告和审定财务报表 `bytes` 有; 您的下水道 自己没有它,则按顺序给文件,作为一个范围,较慢. `{ verify: false }` 当下载到达时, 正在写入, 不加限制 .

在网页上, `@filefreak.io/sdk/badge` 显示: 有盾牌的"验证", 当它被打开,那意味着什么.

```ts
import { verifiedBadge } from "@filefreak.io/sdk/badge";

row.append(verifiedBadge(got.verification));
// After an IntegrityError: verifiedBadge(null, true), "Did not match".
```

它吸收了自身的影子根而没有任何依赖性. 它的颜色是 `--filefreak-verified-good`, (中文(简体) ), `--filefreak-verified-bad` 财务报告和审定财务报表 `--filefreak-verified-muted`检查结果显示,文件是 上传; 它不表示文件可以安全打开 .

## 一个大文件的新版本

16个米B以上的文件在发送和剪切前被读取 它的内容说,每个部分都是它的块之一。 一个新的版本 它,发送与 `onConflict: "replace"`,只发送文件的块 还没有:那些它与里面的新的东西结合在一起 存储。 SDK 和 CLI 切出一个文件, 所以下一个版本的文件 不管是谁派来的 都不要离开.

```ts
await ff.upload(await fromPath("disk.img"), { parentId: folder.id, onConflict: "replace" });
```

在Shard Protection的文件夹中,每个块都一样 离开前加密了 超过 16 MiB 的保护文件被剪切 它自己的钥匙,这样没有钥匙的任何人都可以照样剪掉它的副本 方法与比较,它的下一个版本 保留了最后一个的块 当密钥可能读取文件时; 只能写入的密钥启动新文件 键并发送每个块。 每个区块在发送时都会再次被读取 检查上传的起始内容, 因此文件在上传时更改 发送停止上传( i)`source_changed`),而不是存储两个组合.

## 在网页中

页面是由您的服务器给出一个符号 。 你的服务器是用它的 键 :

```ts
// On your server, behind your own sign-in.
const { token } = await ff.tokens.create({
  scopes: ["files:read", "files:write"],
  folderId: customerFolderId,
  expiresInSeconds: 900,
});
```

页面用它作为钥匙 鉴于一个职能而不是一个 字符串中, SDK 请求您的服务器在最后一个符号耗尽时需要一个新的符号 :

```ts
import { FileFreak } from "@filefreak.io/sdk";

const ff = new FileFreak({
  token: async () => (await fetch("/my-server/filefreak-token")).text(),
});

const input = document.querySelector<HTMLInputElement>("input[type=file]")!;
const file = await ff.upload(input.files![0]!); // into the token's folder
```

一个标志可以做它的关键可能,或更少的: 范围要求 请求文件夹, 从一分钟到一小时。 检查其密钥 每一个请求,所以撤销钥匙 停止它的标志立即。 符号不能 做另一个.

## 预览

服务完成后, 在上传几分钟内, 就会有文件 已经 `thumbnailUrl`,一个图像的小WebP图片,一个来自 iPhone, PDF 第1页, 音频文件标签或框中的封面 视频;或 `previewTextUrl`,文本或代码文件的第一行 文档,作为文本。 两者都是存储本身的地址,不需要钥匙. 每个都是一样的一天,所以一个浏览器 保留它得到的东西,并获取 一无是处 它们是无效的,直到制作, 和一个没有文件.

```ts
const { items } = await ff.files.list({ parent: folder.id });
for (const item of items) {
  if (item.thumbnailUrl) gallery.append(Object.assign(new Image(), { src: item.thumbnailUrl, alt: item.name }));
}
```

`files.preview(item)` 取出一个,并把它还回来 准备使用,因为 `{ kind: "picture", bytes, contentType: "image/webp" }` 或者说 `{ kind: "text", text }`,或者对一个没有的文件无效. `files.previewsOf(items)` 一次对许多人做同样的事情,就像一张由 id 绘制的地图,留下文件 没有.

```ts
const previews = await ff.files.previewsOf(items);
for (const [id, preview] of previews) {
  if (preview.kind === "text") console.log(id, preview.text.split("\n")[0]);
}
```

服务从不看视频, 所以视频的照片是一个框架 你来 在网页上, `upload` 从文件中画出一秒钟左右 页面已存在,一旦文件存储就发送,而不上传 等待着它; `frame: false` 无。 在服务器上,将 JPEG 制作为 并发送:

```ts
import { execFile } from "node:child_process";
import { readFile } from "node:fs/promises";
import { promisify } from "node:util";

// The frame a second in, 960 pixels wide, as a JPEG.
await promisify(execFile)("ffmpeg", ["-ss", "1", "-i", "film.mp4", "-frames:v", "1", "-vf", "scale=960:-2", "-y", "frame.jpg"]);
await ff.files.sendFrame(file.id, new Blob([await readFile("frame.jpg")]));
```

视频的照片是JPEG,最多2 MB,发送一次. Shard 下的文件 保护没有预览 .

## 一个较小的图像

`files.image(id, { size })` 不再提供图像副本的地址 比起来 `size` 最长的一面像素, 如相机元数据 WebP 删除:64、128、256、512、1024或2048。 每个尺寸一次,第一个 时间要求,并保存。 直到得到答案为止 `{ status: "pending", retryAfterSeconds }`,那么那么在那么长的时间之后再问:

```ts
async function sized(id: string, size: number) {
  for (;;) {
    const answer = await ff.files.image(id, { size });
    if (answer.status === "ready") return answer; // { url, width, height, expiresAt }
    await new Promise((r) => setTimeout(r, answer.retryAfterSeconds * 1000));
  }
}
```

在图像上传时命名大小, 并在图像上传时准备好 通缉: `ff.upload(file, { imageSizes: [512, 2048] })`。公开文件 不需要这些:添加 `?size=512` 联合国 `publicUrl`。 。 。 .

## 从链接中保存

`get` 保存共享链接或公共页面。 它不需要钥匙,而且 没有任何信息显示是谁在问:没有密钥,从浏览器看没有 饼干。 文件会进入一个槽; 文件夹需要某个位置 文件,哪个 `toFolder` 在磁盘上.

```ts
import { get } from "@filefreak.io/sdk";
import { toFolder, toPath } from "@filefreak.io/sdk/node";

await get("https://filefreak.link/share/...", await toPath("report.pdf"));

const got = await get("https://filefreak.link/share/...", toFolder("downloads"), {
  password: "open sesame", // for a link that has one
  onProgress: (written, total) => console.log(`${written} of ${total} bytes`),
});
console.log(`${got.files.length} files, ${got.sizeBytes} bytes`);
```

它需要一个共享链接,一个公共文件或文件夹的页面,一个文件的直接 地址 电话 文件夹全部到来: 每个文件到函数生成的下沉 因为它的名字和文件夹。 每个保存的文件都是其中之一 链接的下载,如其页面上的下载, 以及左下方的链接 文件不保存( e)`not_enough_downloads`) (中文(简体) ). Shard 下的文件 保护通过链接的地图读取,并计算一次. 每个文件都是 检查为 `download` 对照SHA -256 连接自己的网站 给它.

链接给出的每一个名称都是其共享者,并且可以是任何东西: `../../.bashrc`, (中文(简体) ), 或者一个反向读取. `toFolder` 让每个人都安全 `safeName` 在写前, 并且从不在文件夹外写它。 一个程序 来自链接本身的名称文件应当使用 `safeName` 我也一样.

## 每个终点

这些功能被归类为参照组: `ff.files`, (中文(简体) ), `ff.folders`, (中文(简体) ), `ff.tree`, (中文(简体) ), `ff.changes`, (中文(简体) ), `ff.uploads`, (中文(简体) ), `ff.usage`, (中文(简体) ), `ff.me`, (中文(简体) ), `ff.tokens` 财务报告和审定财务报表 `ff.shares` (共享链接, 只有设备签名) 输入 `filefreak login` 可能这样做)和 `ff.sites` 一个应用程序的网站,与 允许的密钥 `sites:deploy`地址上的证件先来,然后是尸体或 查询,然后选择:

```ts
const { items, nextCursor } = await ff.files.list({ parent: folder.id, limit: 50 });
await ff.files.update(file.id, { name: "renamed.mp4" });
await ff.files.delete(file.id, { permanent: true });
await ff.sites.update(site.id, { singlePage: false }); // missing pages are 404s again
```

`ff.call("files.get", { params: { id } })` 达到任何终点 名称.

## 读取到结尾

```ts
for await (const item of ff.files.each({ parent: folder.id })) console.log(item.name);

// Everything under a folder, then only what changes.
const walk = ff.tree.walk({ parent: folder.id });
for await (const item of walk) keep(item);
for await (const answer of ff.changes.follow(walk.changesCursor)) {
  for (const change of answer.changes) apply(change);
  save(answer.cursor); // to carry on from after a restart
}
```

`follow` 在API上等待下一次更改,一次一分钟,然后去 ,直到循环左出或其出 `signal` 已中止.

复制件,也发送自己的更改 后名的文件,因为它读它, 这样它就不会重复或删除它没有看到的变化。 无论是 以409拒绝 `revision_changed` 如果文件已移动 :

```ts
await ff.upload(source, { name: file.name, parentId: file.parentId, onConflict: "replace", replacing: { id: file.id, revision: file.revision } });
await ff.files.delete(file.id, { ifRevision: file.revision });
```

## 当上传停止时

所到达的存储被保存到上传过期 。 保留上传代码 从 `onBegun`,并使用同一文件进行:只有部件存储 未发送。 按内容剪取的文件被逐个块地带入, 每个都检查了上传开始的内容, 所以继续另一个 文件在第一个块被拒绝.

```ts
import { UploadStopped } from "@filefreak.io/sdk";

try {
  await ff.upload(source, { name: "big.iso", onBegun: (u) => remember(u.id) });
} catch (e) {
  if (e instanceof UploadStopped) await ff.upload(source, { resume: e.uploadId });
  else throw e;
}
```

## 当某事被拒绝时

拒绝是 `FileFreakError`,与API的 `status`页:1 `code` 没错 不改变,什么是树枝,a `message` 为了一个人.

```ts
import { FileFreakError } from "@filefreak.io/sdk";

try {
  await ff.folders.create({ name: "reports" });
} catch (e) {
  if (e instanceof FileFreakError && e.code === "name_taken") {
    // already there
  } else throw e;
}
```

SDK只有在不能做两次任何事时才会再次发出请求: a 已读;请求中包含一个“同上强度-关键”键,它为每个端点都提出了该键 尊贵的,除非你们自受其赐`{ idempotencyKey }` 输入 选项); 完成上传或制作令牌;或 回答不说 已经做了,例如429。 当服务在静静地咒语后醒来 等待,最多几分钟. `Retry-After` 很荣幸.

## 许可证

阿帕奇2.0 (英语).

## 常见问题

### @filefreak\.io/sdk 是什么？

FileFreak的开发者API用于节点和浏览器:每个端点,直接上传到部分存储,下载范围,以及接下来的更改\.

### 如何安装 @filefreak\.io/sdk？

在项目目录运行 npm install @filefreak\.io/sdk，或使用 pnpm add / yarn add / bun add。

### @filefreak\.io/sdk 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @filefreak\.io/sdk 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @filefreak\.io/sdk 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=20。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @filefreak\.io/sdk 可以商用吗？

@filefreak\.io/sdk 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @filefreak\.io/sdk 的下载量有多少？

根据 npm 官方下载统计，@filefreak\.io/sdk 在 2026/10/15 – 2026/11/13 这 30 天内被下载 4,374 次，日均约 146 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @filefreak\.io/sdk 还在维护吗？

最新版本 0\.20\.0 发布于 2026/11/11（3 天前）；至今共发布 23 个版本，其中过去 12 个月发布了 23 个；首次发布于 2026/10/26。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

