婚礼回忆:合作婚礼相册!
婚礼回忆
婚礼回忆
这是Pinata 挑战赛的参赛作品
我建造了什么
Wedding Memories是一款旨在捕捉、分享和珍藏您特别日子里每一个难忘瞬间的应用!它允许婚礼宾客轻松上传照片,创建协作相册,捕捉婚礼的精髓。通过使用Pinata 的文件 API,该应用可提供安全高效的媒体上传和存储体验。
演示
点击此处查看该应用程序的实时版本:婚礼回忆
截图:
- 上传部分- 用于选择和上传媒体文件的用户友好界面:
- 画廊视图- 以响应式布局显示所有已上传的回忆:
- 移动优化设计- 确保所有设备上的流畅用户体验:
- 下载选项- 客人可以下载自己最喜欢的时刻以永远保留回忆。
我的代码
您可以在 GitHub 上探索该项目的完整代码:
更多详情
Wedding Memories 利用 Pinata 的 Files API 构建安全高效的文件上传功能。以下是集成的简要说明:
-
文件上传:宾客可直接从设备轻松上传图片。此操作通过 实现
pinata.upload.file
,它使用基于 JWT 的身份验证来确保文件处理的安全。上传后,文件将被安全存储,并生成其唯一标识符 (CID) 以供检索。 -
上传前本地预览:为了提升宾客体验,婚礼回忆会在上传照片前生成本地预览。此功能允许宾客确认选择并进行调整,确保只提交他们想要的照片。
上传成功后,文件将通过文件 API进行渲染。这确保了内容的快速访问,为访客在查看共享记忆时提供无缝体验。
- 下载功能:宾客现在可以直接从应用程序下载自己喜爱的照片,轻松将珍贵的回忆保存到设备中。该应用程序包含一个API路由,方便安全地下载文件。
API 集成细分:
该建筑包括几个关键的 API 路线,每个路线旨在处理特定的功能:
- 文件上传端点
它接受文件上传并使用 Pinata 的上传功能进行存储。然后,它会生成一个签名的 URL,以便轻松访问上传的文件。
import { NextResponse, NextRequest } from "next/server";
import { pinata } from "../../../../utils/config";
export async function POST(request: NextRequest) {
try {
const data = await request.formData();
const file: File | null = data.get("file") as unknown as File;
const uploadData = await pinata.upload.file(file)
const url = await pinata.gateways.createSignedURL({
cid: uploadData.cid,
expires: 3600,
});
return NextResponse.json(url, { status: 200 });
} catch (e) {
console.log(e);
return NextResponse.json(
{ error: "Internal Server Error" },
{ status: 500 }
);
}
}
- API 密钥生成
(/api/key/route.ts)
:
创建一个临时 API 密钥,并赋予其将文件固定到 IPFS 的权限。
/* eslint-disable @typescript-eslint/no-unused-vars */
import { NextResponse } from "next/server";
import { pinata } from "../../../../utils/config";
export const dynamic = "force-dynamic";
export async function GET() {
try {
const uuid = crypto.randomUUID();
const keyData = await pinata.keys.create({
keyName: uuid.toString(),
permissions: {
endpoints: {
pinning: {
pinFileToIPFS: true,
},
},
},
maxUses: 1,
})
return NextResponse.json(keyData, { status: 200 });
} catch (error) {
console.log(error);
return NextResponse.json({ text: "Error creating API Key:" }, { status: 500 });
}
}
- 列出文件
(/api/listfiles/route.ts)
:
从 Pinata 检索已上传文件的列表,允许用户查看图库中的所有共享内容
import { NextResponse } from "next/server";
import { env } from "process";
export const dynamic = "force-dynamic";
export async function GET() {
try {
const options: RequestInit = {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.NEXT_PUBLIC_PINATA_JWT}`,
},
cache: 'no-cache'
};
const response = await fetch('https://api.pinata.cloud/v3/files', options);
if (!response.ok) {
return NextResponse.json({ text: "Error listing files" }, { status: response.status });
}
const { data } = await response.json();
return NextResponse.json(data, { status: 200 });
} catch (error) {
console.log(error, "Error listing files");
return NextResponse.json({ text: "Error listing files" }, { status: 500 });
}
}
- 图像代理
(/api/proxy/route.ts)
:
充当从外部来源获取图像的代理,确保用户可以轻松访问和下载他们的图像。
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const imageUrl = searchParams.get('url'); // Get the image URL from the query string
if (!imageUrl) {
return NextResponse.json({ error: 'Image URL is required' }, { status: 400 });
}
try {
const response = await fetch(imageUrl);
if (!response.ok) {
return NextResponse.json({ error: 'Failed to fetch image' }, { status: response.status });
}
const contentType = response.headers.get('content-type') || 'application/octet-stream';
const imageBuffer = await response.arrayBuffer();
return new NextResponse(imageBuffer, {
headers: {
'Content-Type': contentType,
'Content-Disposition': 'attachment; filename="downloaded_image"',
},
});
} catch (error) {
console.error('Error fetching image:', error);
return NextResponse.json({ error: 'Error fetching image' }, { status: 500 });
}
}
- 签名 URL 创建
(/api/sign/route.ts)
:
为上传的文件生成签名的 URL。
import { type NextRequest, NextResponse } from "next/server";
import { pinata } from "../../../../utils/config";
export const dynamic = "force-dynamic";
export async function POST(req: NextRequest) {
try {
const data = await req.json();
const mimeType = data.mime_type;
let url;
if (mimeType === 'video/mp4') {
url = await pinata.gateways.createSignedURL({
cid: data.cid,
expires: 7776000,
})
} else {
url = await pinata.gateways.createSignedURL({
cid: data.cid,
expires: 7776000,
}).optimizeImage({
width: 300,
height: 300,
format: "webp",
fit: "contain",
quality: 90,
dpr: 2,
sharpen: 1,
});
}
return NextResponse.json(url, { status: 200 });
} catch (error) {
console.log(error);
return NextResponse.json({ text: "Error creating signed URL:" }, { status: 500 });
}
}
该应用程序采用以下方式构建:
-
Pinata:文件 API
-
前端:React、Next.js、Framer Motion
-
样式:Tailwind CSS 用于响应式、美观的布局。
-
托管:放大部署。
结论
婚礼是充满爱意、欢笑和无数难忘瞬间的欢乐时刻。捕捉这些珍贵的回忆至关重要,有了婚礼回忆 (Wedding Memories)应用,记录婚礼瞬间变得前所未有的轻松!
该应用程序允许每位嘉宾在活动当天拍摄可爱的照片并无缝分享,确保不会错过任何瞬间,让每个人都能享受庆祝活动的集体回忆。
该应用程序利用Pinata 文件 API的强大功能,为客人提供一种安全高效的方式来上传和分享他们的照片和视频,从而创建一个完美概括当天精髓的协作相册。
有关该应用程序如何与 Pinata 集成以及探索其功能的更多详细信息,请参阅Pinata 文档。
谢谢。
鏂囩珷鏉ユ簮锛�https://dev.to/femi_akinyemi/wedding-memories-the-collaborative-wedding-album-2em3