@apicity/ free- media- upload (帮助)
0-Auth文件托管包装器用于收件箱,gofile,ugu,filebin,垃圾箱,tirsh,tflink,和tmpfiles——一个打入的表面后面有8个提供者.
运行时间依赖性 :
zod@^4.6.6- 请求在每一个 POST 端点上附加计划.schema
安装
npm install @apicity/free-media-upload
# or
pnpm add @apicity/free-media-upload
快速启动
import { createFreeMediaUpload } from "@apicity/free-media-upload";
const freeMediaUpload = createFreeMediaUpload();
真实世界的例子: 在四个免费主机之间比赛一张肖像
@apicity/free-media-upload 覆盖8个零自动、无账户文件托管端点
在一个打字的地表后面——胜利可以同样扇出 Blob
输出到并行的多个主机, 然后选择任何 URL 返回
首先(或任何幸存者)不重写四个不同的多部分
召来者. 下面的片段上传了单张84 KB JPEG 到四张
最富有的反应形状——收件箱(平面字符串),去文件(丰富的捆绑)
元数据),ugu(随机重命名+dupe检测),filebin(md5/sha256+)
——并显示如何在其中一种情况下使其正常化 toUrl() 帮手.
下面的每个 URL、字节数和散列都是从
tests/recordings/free_2578706139/, (中文(简体) ),
重播者为
tests/integration/free-catbox.test.ts, (中文(简体) ),
tests/integration/free-gofile.test.ts, (中文(简体) ),
tests/integration/free-uguu.test.ts, (中文(简体) ),
tests/integration/free-filebin.test.ts, (中文(简体) ),
财务报告和审定财务报表 tests/integration/free-litterbox.test.ts。 。 。 .
import { readFileSync } from "node:fs";
import { createFreeMediaUpload } from "@apicity/free-media-upload";
import type { GofileUploadResponse, UguuUploadResponse, FilebinUploadResponse } from "@apicity/free-media-upload";
// 1. The factory takes no api key — every host below is genuinely
// auth-free and account-free. Pass `{ timeout: 60_000 }` or a
// custom `fetch` if you need to override the defaults.
const freeMediaUpload = createFreeMediaUpload();
const bytes = readFileSync("./cat1.jpg"); // 83,558 bytes
const file = new Blob([bytes], { type: "image/jpeg" });
// 2. Race four hosts in parallel via Promise.all. Each returns a
// different shape: catbox/litterbox/tempsh hand back a plain
// `string` URL, gofile/tflink return a metadata bundle, uguu's
// payload nests under `files[]`, and filebin splits things into
// `bin` + `file` blocks. The factory keeps these distinctions in
// the type system so the destructure below is statically checked.
const [catboxUrl, gofile, uguu, filebin] = (await Promise.all([
freeMediaUpload.catbox.upload({ file, filename: "cat1.jpg" }),
freeMediaUpload.gofile.upload({ file, filename: "cat1.jpg" }),
freeMediaUpload.uguu.upload({ file, filename: "cat1.jpg" }),
freeMediaUpload.filebin.upload({ file, filename: "cat1.jpg", bin: "apicity-test-img" }),
])) as [string, GofileUploadResponse, UguuUploadResponse, FilebinUploadResponse];
// 3. catbox is the simplest UX: text/plain response, just the URL,
// permanent until the operator deletes it. Good for a 'host once,
// forget' public asset.
console.log(catboxUrl);
// → "https://files.catbox.moe/0ufdor.jpg"
// 4. gofile is the only host that gives you a sharable download page
// (suitable for human consumption) plus a CDN-direct id you can use
// to build APIs against. The `parentFolderCode` is a 6-char folder
// handle — every upload lands in a fresh anonymous folder unless
// you authenticate.
console.log(gofile.data.downloadPage);
// → "https://gofile.io/d/hmoMxW"
console.log(gofile.data.id, gofile.data.md5, gofile.data.size);
// → "a7feccb4-96b4-4b2c-923a-832106388ad6" "391a26048ce697ba072acd83209923f7" 83558
// 5. uguu rewrites filenames to a random 8-char slug to stop URL
// enumeration, and tells you whether your bytes were already on
// the host (`dupe: true`) so you can skip a re-upload next time.
// Note the `files[]` array — uguu accepts batched uploads via the
// same endpoint, even though @apicity/free-media-upload only ships single-file.
console.log(uguu.files[0].url, uguu.files[0].dupe);
// → "https://n.uguu.se/GeNMsbBp.jpg" false
// 6. filebin verifies content integrity for you — it returns both
// md5 and sha256, plus an expiry. The `bin` is a namespace you can
// re-upload into to grow a multi-file bundle (omit `bin` and you
// get an auto-generated one). Files in a bin expire together on
// `bin.expired_at`.
console.log(filebin.file.md5, filebin.file.sha256);
// → "ORomBIzml7oHKs2DIJkj9w==" "561dbe5dcd0c931cd3b41705ebe00df9181560967cea8b17128373a06ab911a3"
console.log(`bin "${filebin.bin.id}" expires ${filebin.bin.expired_at}`);
// → 'bin "apicity-test-img" expires 2026-04-23T07:19:25.458442Z'
// 7. Hosts that return strings already give you a URL; hosts that
// return JSON bury it under different keys. A tiny normaliser lets
// downstream code stop caring which host won the race.
function toUrl(
res: string | GofileUploadResponse | UguuUploadResponse | FilebinUploadResponse,
bin?: string,
filename?: string,
): string {
if (typeof res === "string") return res;
if ("data" in res) return res.data.downloadPage; // gofile
if ("files" in res) return res.files[0].url; // uguu
return `https://filebin.net/${bin}/${filename}`; // filebin
}
console.log([
toUrl(catboxUrl),
toUrl(gofile),
toUrl(uguu),
toUrl(filebin, "apicity-test-img", "cat1.jpg"),
]);
// → [
// "https://files.catbox.moe/0ufdor.jpg",
// "https://gofile.io/d/hmoMxW",
// "https://n.uguu.se/GeNMsbBp.jpg",
// "https://filebin.net/apicity-test-img/cat1.jpg",
// ]
跨时空主机失败
当您只需要一个 URL 就可以活上几个小时时
下游的型号 即将得到它一次,然后忘记.. @apicity/free-media-upload
船舶a uploadToAnyHost 随机移动主机列表并
返回第一个成功的 URL, 升起单个 FreeMediaUploadError 只有在
每个主机失败 。 当一个供应商是 Flashy 时有用( guu 的 CDN 可以 502)
不过你不在乎谁赢了.
import { readFileSync } from "node:fs";
import { createFreeMediaUpload, uploadToAnyHost, FreeMediaUploadError } from "@apicity/free-media-upload";
const freeMediaUpload = createFreeMediaUpload();
const bytes = readFileSync("./cat1.jpg");
const file = new Blob([bytes], { type: "image/jpeg" });
// litterbox accepts a TTL; uguu and tflink are best-effort permanent.
// uploadToAnyHost shuffles the list and tries each host sequentially,
// so a single 502 from uguu falls through to tflink without your code
// ever seeing it. The returned URL is already normalised — string in,
// string out, regardless of which host responded.
try {
const url = await uploadToAnyHost(freeMediaUpload, {
file,
filename: "cat1.jpg",
hosts: ["litterbox", "uguu", "tflink"],
time: "12h", // forwarded to litterbox if it wins the shuffle
});
console.log(url);
// → "https://litter.catbox.moe/04obtk.jpg" // example: litterbox won
} catch (err) {
if (err instanceof FreeMediaUploadError) {
// err.body.failures is a string[] of `<host>: <message>` lines —
// useful for surfacing exactly which hosts misbehaved.
console.error(err.status, err.body);
}
}
页:1
- 所有8个终点
{ file: Blob, filename?: string }收发箱 和垃圾箱回复text/plain(URL本身);tmp文件, uguu, gofile, filebin, and tflink 返回 JSON; 临时返回平原 语句。 工厂对每一个都进行了正确分析 这样你就不会看到原始的 身体——只是打入的形状. litterbox.upload唯一的终点是time字段 -"1h" | "12h" | "24h" | "72h"超过72小时的任何需要 永久托管兄弟姐妹(catbox, gofile, filebin).filebin.upload是个二进制POST(无) 多块包装,所以Blob电线是... .. 服务器处理<bin>/<filename>作为上传目标。 重新装入 改为:bin将文件添加到捆绑中而不是替换 它; 预创建一个稳定binshult来生长多文件集.- gofile (英语)
guestToken是这个供应商最接近的 认证手柄 – 如果您想稍后删除上传内容, 请保存它 gofile API (英语). 没有它,匿名上传只写. - 每个端点都暴露出一个Zod计划:
freeMediaUpload.catbox.upload.schema.safeParse(input)验证有效载荷 在网络呼叫之前,它发现了最常见的错误 (通过a)Buffer或者说string而不是一个Blob) (中文(简体) ). - 所有终点都接受
AbortSignal第二个参数和作曲 与withRetry编号 :withFallback从@apicity/free-media-upload中间软件 再出口——用于出行429s的出行口袋或链式出行口袋—— 作为倒背的一对. - 丢出错误
FreeMediaUploadError与status和附着的解析体:try { ... } catch (e) { if (e instanceof FreeMediaUploadError) console.error(e.status, e.body); }。 。 。 .
API 参考
8个终点横跨了8组. 每个方法都映射出上游的 URL 路径 .
纸箱
POST free-media-upload.catbox.upload
POST https://catbox.moe/user/api.php
成本等级 : cheap
const res = await freeMediaUpload.catbox.upload({ /* ... */ });
资料来源: packages/provider/free-media-upload/src/freeMediaUpload.ts
文件编辑器
POST free-media-upload.filebin.upload
POST https://filebin.net/{bin}/{filename}
成本等级 : cheap
const res = await freeMediaUpload.filebin.upload({ /* ... */ });
资料来源: packages/provider/free-media-upload/src/freeMediaUpload.ts
进程文件
POST free-media-upload.gofile.upload
POST https://upload.gofile.io/uploadfile
成本等级 : cheap
const res = await freeMediaUpload.gofile.upload({ /* ... */ });
资料来源: packages/provider/free-media-upload/src/freeMediaUpload.ts
垃圾箱
POST free-media-upload.litterbox.upload
POST https://litterbox.catbox.moe/resources/internals/api.php
成本等级 : cheap
const res = await freeMediaUpload.litterbox.upload({ /* ... */ });
资料来源: packages/provider/free-media-upload/src/freeMediaUpload.ts
临时
POST free-media-upload.tempsh.upload
成本等级 : cheap
const res = await freeMediaUpload.tempsh.upload({ /* ... */ });
资料来源: packages/provider/free-media-upload/src/freeMediaUpload.ts
链接
POST free-media-upload.tflink.upload
POST https://tmpfile.link/api/upload
成本等级 : cheap
const res = await freeMediaUpload.tflink.upload({ /* ... */ });
资料来源: packages/provider/free-media-upload/src/freeMediaUpload.ts
tmp文件
POST free-media-upload.tmpfiles.api.v1.upload
POST https://tmpfiles.org/api/v1/upload
成本等级 : cheap
const res = await freeMediaUpload.tmpfiles.api.v1.upload({ /* ... */ });
资料来源: packages/provider/free-media-upload/src/freeMediaUpload.ts
乌古
POST free-media-upload.uguu.upload
成本等级 : cheap
const res = await freeMediaUpload.uguu.upload({ /* ... */ });
资料来源: packages/provider/free-media-upload/src/freeMediaUpload.ts
中间软件
import { createFreeMediaUpload, withRetry } from "@apicity/free-media-upload";
const freeMediaUpload = createFreeMediaUpload();
const upload = withRetry(freeMediaUpload.uguu.upload, { retries: 3 });
部分 辣点 单相机.
许可证
麻省理工学院——见 自由主义。 。 。 .