@ filefreak.io/sdk (英语)
FileFreak 开发者 API,来自 TypeScript 或 JavaScript, 在节点 20 和 后入并入于浏览器. 无相依相.
每个端点都是函数,从相同的表格中键入 API 构建 从. 周围:直接上传至部分存储并继续进行 中断后, 一个大文件的新版本只发送什么 已更改, 下载到区域中, 并对照文件 SHA-256,列表和修改读取到尾端,被发送并读取的被Shard Protection下的文件被密封 通过他们的地图,共享链接所保存的没有密钥,并且请求仅在此时再次发出 无法使任何东西两次。 参考文献为: https://filefreak.io/developers/参考文献 互联网档案馆的存檔,存档日期2014-12-22。 。 。 .
在服务器上
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 留下任何东西.
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 显示: 有盾牌的"验证",
当它被打开,那意味着什么.
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 切出一个文件, 所以下一个版本的文件
不管是谁派来的 都不要离开.
await ff.upload(await fromPath("disk.img"), { parentId: folder.id, onConflict: "replace" });
在Shard Protection的文件夹中,每个块都一样
离开前加密了 超过 16 MiB 的保护文件被剪切
它自己的钥匙,这样没有钥匙的任何人都可以照样剪掉它的副本
方法与比较,它的下一个版本 保留了最后一个的块
当密钥可能读取文件时; 只能写入的密钥启动新文件
键并发送每个块。 每个区块在发送时都会再次被读取
检查上传的起始内容, 因此文件在上传时更改
发送停止上传( i)source_changed),而不是存储两个组合.
在网页中
页面是由您的服务器给出一个符号 。 你的服务器是用它的 键 :
// On your server, behind your own sign-in.
const { token } = await ff.tokens.create({
scopes: ["files:read", "files:write"],
folderId: customerFolderId,
expiresInSeconds: 900,
});
页面用它作为钥匙 鉴于一个职能而不是一个 字符串中, SDK 请求您的服务器在最后一个符号耗尽时需要一个新的符号 :
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,文本或代码文件的第一行
文档,作为文本。 两者都是存储本身的地址,不需要钥匙.
每个都是一样的一天,所以一个浏览器 保留它得到的东西,并获取
一无是处 它们是无效的,直到制作, 和一个没有文件.
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 绘制的地图,留下文件
没有.
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 制作为
并发送:
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 },那么那么在那么长的时间之后再问:
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 在磁盘上.
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地址上的证件先来,然后是尸体或
查询,然后选择:
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 } }) 达到任何终点 名称.
读取到结尾
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 如果文件已移动 :
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,并使用同一文件进行:只有部件存储
未发送。 按内容剪取的文件被逐个块地带入,
每个都检查了上传开始的内容, 所以继续另一个
文件在第一个块被拒绝.
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 为了一个人.
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 (英语).