这是Pina塔挑战的提交
我创建的Uploadnow 是一个允许用户轻松上传和管理文件(图片、视频、音频等)的网络应用。它使用 Pinata 来存储和检索,从而为资产管理工作提供了一个安全且一致的环境。此项目是 Pinata 挑战赛的提交作品。我的灵感来自 Uploadthing。
先修条件:
- Node.js的基础知识。
- Pinata SDK,用于处理文件的上传。
- Convex.dev 的实时数据库。
- Next.js 和 Tailwind CSS。
要初始化一个新的 ShadCN Next.js 项目,可以运行下面的命令:
运行以下命令来初始化项目:
npx shadcn@latest init
或者
pnpm dlx shadcn@latest init
全屏,退出
创建一个名为 .env.local
的文件,并将以下内容粘贴进去:,
PINATA_API_KEY=""
PINATA_API_SECRET=""
PINATA_GATEWAY="*.mypinata.cloud"
PINATA_JWT=""
# è®°é¢ANCER `npx convex dev` 解颮
CONVEX_DEPLOYMENT=""
NEXT_PUBLIC_CONVEX_URL=""
# 记颮讵権屮
FINGER_PRINT_API_KEY=""
全屏,退出全屏
特点:
- 响应式设计:应用程序设计为可以在移动设备和桌面电脑上使用。
- 用户友好型界面:用户界面被简化,移除了不必要的UI元素,并使用易于理解的文本说明和弹出通知。
- 简洁的错误消息:我专注于从用户的角度而不是开发者的角度创建用户友好的错误消息。
- 高效的文件上传:文件上传功能允许用户上传各种类型的文件。文件会被排队,支持如
upload
、cancel
、retry
和remove file
等操作。 - 多文件上传:支持用户同时上传多个文件。
- 实时支持:提供实时技术支持或帮助。
- 分页:实现分页浏览以便用户查看更多内容。
- 使用CDN:用户可以在新标签中打开文件,并且链接在几秒钟后过期,以增加安全性。使用浏览器的唯一标识来关联和区分用户。
- 无需登录:使用浏览器的独特特征来识别用户,而不需要用户名和密码。
该项目需要Pinata的凭证,然后请前往[仪表板]查看详情。
- 请输入您的个人信息。
- 这是你的主页/控制面板。
- 点击“API密钥”标签,新建一个密钥。
给密钥取个名字,选好权限后,点击一下生成密钥。
- 请复制您的凭证并安全保存,因为这些凭证只会显示一次。如果忘记或丢失,可以生成新的凭证。
已部署的应用版本可以在Uploadnow查看。
看看上传队列
上传进度如下,
我的程序代码1. 派对气球上传
这是由 Next.js 提供的路由处理器。它是一个 POST 请求处理器(handler),接收文件和其他必要的信息。通过调用 await pinata.upload.file(file)
方法,并将文件对象作为第一个参数传递,将文件传递给 Pinata
的 JavaScript SDK。
export const POST = async (req: Request) => {
try {
const form = await req.formData();
const file = form.get("file") as File;
const sidebarId = form.get("sideBarId") as Sidebar;
const fingerPrintId = form.get("visitorId") as string;
if (!file || !sidebarId || !fingerPrintId) {
return Response.json(
{ message: "请求无效,请提供所有参数。" },
{ status: 403 }
);
}
const upload = await Pinata.upload.file(file);
const convexDb = await fetchMutation(api.files.createFile, {
sidebarId,
fingerPrintId,
pinataId: upload.id,
filename: upload.name,
pinataCid: upload.cid,
mimeType: upload.mime_type,
pinataCreatedAt: upload.created_at,
});
if (!convexDb) {
return Response.json(
{ message: "无法上传文件,请重试上传。", uploaded: false },
{ status: 500 }
);
}
return Response.json({ message: convexDb.message, uploaded: true });
} catch (err: any) {
console.error(err);
return Response.json(
{ message: "服务器内部错误,请稍后再试。" },
{ status: 500 }
);
}
};
切换到全屏 退出全屏
2. 设置凸形数据库架构
因为这个项目用的是Convex,所以我们要设置数据库结构。由于我们使用了Fingerprint.js,所以不需要单独的用户表。
import { defineSchema, defineTable, GenericSchema } from "convex/server";
import { v } from "convex/values";
// 定义文件模式
export default defineSchema({
files: defineTable({
// 文件指纹ID
fingerPrintId: v.string(),
// Pinata ID
pinataId: v.string(),
// Pinata Cid
pinataCid: v.string(),
// 文件名
filename: v.string(),
// MIME类型
mimeType: v.string(),
// Pinata创建时间
pinataCreatedAt: v.string(),
// 侧边栏ID
sidebarId: v.union(
v.literal("all"),
v.literal("audios"),
v.literal("videos"),
v.literal("images"),
v.literal("documents"),
v.literal("archives")
),
}),
});
全屏,退出全屏
Uploadnow这个项目的完整源代码可以在GitHub访问。
了解更多常见问题:
- 包含缺陷的列表方法:
我最初的计划是将Pinata中的群组功能整合进来,但由于群组列表的方法不起作用,我不得不重新考虑一下这个功能是否可行。
const groups = await pinata.groups.list();
这行代码用于从pinata的groups列表中获取分组信息。
切换到全屏 / 退出全屏
当该方法被调用时,它只是返回一个空数组。即使更改了秘密凭证也无法使其工作。最终REST API才开始能用上了,而那时我已经转向了其他功能。在REST API和SDK之间切换体验并不好。
发送失败:无法从客户端发送资产
Pinata 的 API 很直观,但我找不到从客户端直接将资产发送到 Pinata 的方法。此功能可以节省服务器资源,因为它可以直接从客户端上传到 Pinata,而不需要先上传到我的服务器。我不是说现在的做法不好,只是对开发者来说,特别是像可暂停上传这样的功能,客户端直接上传功能会更好。
建议:
作为一名重视提升开发体验的工具的开发者,这里有一些推荐。
- 提供默认的资产链接:允许开发人员选择生成签名链接或使用默认链接。没有默认的资产链接可能会让开发人员重新考虑他们的集成策略,这可能促使他们寻找替代方案。这也会带来一些UI上的挑战,因为开发人员需要意识到这个问题才能有效地集成API,否则可能会遇到困难。
- 返回错误和数据元组:SDK应返回错误和数据元组,让开发人员能够根据情况选择如何处理。
// Supabase示例代码
const { error, data } = await pinata.upload.file(file);
if (error) {
throw new PlatformError("Pinata文件上传失败了。");
}
全屏 退出全屏
- 增加对重试策略的支持:当SDK失败时,应自动重试,使其更加强大。
我独自一人完成了这个挑战。
致谢
我使用了一个开源的Shadcn模板作为基础,具体来说,我使用了来自uploader.sadmn.com的上传对话框功能来处理资产的上传。应用程序的其余部分都是我一个人完成的。这个模板只贡献了不到整体代码库2%的代码。
结论如下:
这个挑战既不激烈也不太有挑战性,但非常有教育意义。我学到了很多关于文件的知识,以及如何考虑用户体验的方法。今天的分享就到这里啦!敬请期待更多的更新,继续打造超棒的应用程序吧!🚀✨
祝你编程愉快!😊
共同学习,写下你的评论
评论加载中...
作者其他优质文章