这是提交给Pinata挑战的。
我建造的东西婚礼回忆录是一款专为捕捉、分享并珍藏您特别日子中的每一个珍贵瞬间而设计的应用程序!它允许婚礼宾客轻松上传照片,共同创建一个反映婚礼精髓的相册。通过使用Pinata的文件API,该应用为安全高效地上传和存储媒体提供了无缝体验。
演示试试看这个应用的实时版本:Wedding Memories(婚礼回忆)
截图如下。
- 上传区 — 方便选择并上传媒体文件:
如图所示:
- 画廊视图功能 - 以响应式布局展示所有上传的记忆,
看这张图片:
- 响应式设计 - 确保在各种设备上都有流畅的用户界面和体验
- 下载选项: 游客可以下载他们最喜爱的瞬间,留住美好回忆。
如图所示
我的代码你可以在这里查看该项目的全部代码。
更多详细信息《婚礼回忆》利用Pinata的Files API来构建安全且高效的文件上传。以下是该集成的简要介绍:
-
文件上传:用户可以轻松地从设备直接上传图片。这通过使用
pinata.upload.file
实现,该功能采用JWT认证以确保文件处理的安全性。上传后,上传的文件将安全存储,并生成唯一的CID以便检索。 - 上传前的本地预览:为了提升宾客体验,婚礼照片会在上传照片前生成本地预览。此功能允许宾客确认并调整,确保上传的照片正是他们想要的。
文件成功上传后,文件会被file 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: "服务器内部错误" },
{ 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: "创建API密钥时出错:" }, { status: 500 });
}
}
进入全屏模式 退出全屏模式
- 文件列表 API 路由
(/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 ${env.PINATA_JWT}`, // 注:Bearer令牌用于授权请求
},
cache: 'no-cache'
};
const response = await fetch('https://api.pinata.cloud/v3/files', options);
if (!response.ok) {
return NextResponse.json({ text: "列出文件失败" }, { status: response.status });
}
const { data } = await response.json();
return NextResponse.json(data, { status: 200 });
} catch (error) {
console.log(error, "列出文件失败");
return NextResponse.json({ text: "服务器内部错误" }, { 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'); // 获取URL参数
if (!imageUrl) {
return NextResponse.json({ error: '请提供图像的URL' }, { status: 400 });
}
try {
const response = await fetch(imageUrl);
if (!response.ok) {
return NextResponse.json({ error: '无法加载图像' }, { 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);
return NextResponse.json({ error: '获取图像失败' }, { 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: "生成签名URL时出错:" }, { status: 500 });
}
}
全屏 退出全屏
该应用程序是由以下技术构建的。请提供具体的技术信息,以便翻译。
-
Pinata:文件API接口
-
前端 :React,Next.js,Framer Motion
-
样式设计:采用 Tailwind CSS 来实现美观且响应式的布局。
- 托管在 Vercel 上:使用 Vercel 进行部署。
婚礼是充满爱、笑声和无数难忘瞬间的欢乐时刻。捕捉这些珍贵的回忆非常重要,而有了这款 [婚礼记忆]() 应用,现在变得比以前更加简单!
这款应用允许每位客人在活动当天拍下美好瞬间并轻松分享,确保不放过任何瞬间,让每个人都能访问庆祝活动的共同记忆。
该应用程序利用Pinata的文件API的功能,让宾客可以安全高效地上传和分享他们的照片和视频,共同创建一个完美记录这一天美好时光的相册。
了解该应用如何与Pinata集成及功能详情,请参见Pinata的文档。
谢谢。
此处省略