Moh*_*ele 1 cloudflare reactjs next.js cloudflare-workers
我最近遇到了 Cloudflare 的 R2 存储桶。这个桶有大量的免费套餐,我想将其用于我的个人项目。但没有关于如何在下一个 JS 13 中使用它的文档。可能有一些教程展示如何在 Node js 中使用它。
那么我如何使用 Next 13 API 路由上传到 R2 存储?
从我的 reddit 评论中复制这个解决方案。我选择了选项 2:直接从浏览器上传到 AWS S3
\n不敢相信没有人写过有关使用 cloudflare r2 与 next 13 目录的指南app/
,所以我只是做了 \xe2\x86\x93
[\n {\n "AllowedOrigins": [\n "http://localhost:3000"\n ],\n "AllowedMethods": [\n "GET",\n "PUT",\n "POST",\n "HEAD",\n "DELETE"\n ],\n "AllowedHeaders": [\n "*"\n ],\n "ExposeHeaders": [],\n "MaxAgeSeconds": 3000\n }\n]\n
Run Code Online (Sandbox Code Playgroud)\nnpm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
\n\n\n从 cloudflare r2 仪表板生成令牌。在 Cloudflare Workers YouTube 频道上观看官方 YouTube 视频
\n
R2_ACCESS_KEY_ID=xxxx\nR2_SECRET_ACCESS_KEY=xxxx\nR2_BUCKET_NAME=xxxx\nR2_ACCOUNT_ID=xxxx\n
Run Code Online (Sandbox Code Playgroud)\nimport { S3Client } from \'@aws-sdk/client-s3\'\n\nexport const r2 = new S3Client({\n region: \'auto\',\n endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,\n credentials: {\n accessKeyId: process.env.R2_ACCESS_KEY_ID || \'\',\n secretAccessKey: process.env.R2_SECRET_ACCESS_KEY || \'\',\n },\n})\n
Run Code Online (Sandbox Code Playgroud)\n\'use client\'\nimport React from \'react\'\nimport { DocumentIcon } from \'@heroicons/react/24/solid\'\n\nconst Admin = () => {\n const [file, setFile] = React.useState<File>()\n\n const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (event.target.files) {\n const currentFile = event.target.files[0]\n setFile(currentFile)\n }\n }\n\n const handleUpload = async () => {\n if (!file) return\n\n const formData = new FormData()\n formData.append(\'file\', file)\n\n const response = await fetch(\'/api/upload\', {\n method: \'POST\',\n })\n const { url } = await response.json()\n await fetch(url, {\n method: \'PUT\',\n body: formData,\n })\n }\n\n return (\n <div className="min-h-screen bg-slate-900 text-white space-y-12">\n <div className="max-w-2xl mx-auto py-24 px-4">\n <h2 className="text-base font-semibold leading-7 text-white">\n Admin Panel\n </h2>\n <p className="mt-1 text-sm leading-6 text-gray-400">\n Upload the latest version of the pdf file.\n </p>\n\n <div className="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">\n <div className="col-span-full">\n <label\n htmlFor="pdf-file"\n className="block text-sm font-medium leading-6 text-white"\n >\n PDF\n </label>\n <div className="mt-2 flex justify-center rounded-lg border border-dashed border-white/25 px-6 py-10">\n <div className="text-center">\n <DocumentIcon\n className="mx-auto h-12 w-12 text-gray-500"\n aria-hidden="true"\n />\n <div className="mt-4 text-sm leading-6 text-gray-400">\n <label\n htmlFor="file-upload"\n className="relative cursor-pointer rounded-md bg-gray-900 font-semibold text-white focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-600 focus-within:ring-offset-2 focus-within:ring-offset-gray-900 hover:text-indigo-500"\n >\n <span>Upload a file</span>\n <input\n type="file"\n accept="application/pdf"\n id="file-upload"\n name="file-upload"\n className="sr-only"\n onChange={handleFileChange}\n />\n </label>\n </div>\n <p className="text-xs leading-5 text-gray-400">\n {file?.name ? file.name : \'PDF up to 100MB\'}\n </p>\n </div>\n </div>\n </div>\n </div>\n <div className="mt-6 flex items-center justify-end gap-x-6">\n <button\n type="submit"\n className="rounded-md bg-indigo-500 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500"\n onClick={handleUpload}\n >\n Upload\n </button>\n </div>\n </div>\n </div>\n )\n}\n\nexport default Admin\n
Run Code Online (Sandbox Code Playgroud)\nimport { NextResponse } from \'next/server\'\nimport chalk from \'chalk\'\nimport { PutObjectCommand } from \'@aws-sdk/client-s3\'\nimport { getSignedUrl } from \'@aws-sdk/s3-request-presigner\'\n\nimport { r2 } from \'@/lib/r2\'\n\nexport async function POST(request: Request) {\n try {\n console.log(chalk.yellow(`Generating an upload URL!`))\n\n const signedUrl = await getSignedUrl(\n r2,\n new PutObjectCommand({\n Bucket: process.env.R2_BUCKET_NAME,\n Key: `filename.pdf`,\n }),\n { expiresIn: 60 }\n )\n\n console.log(chalk.green(`Success generating upload URL!`))\n\n return NextResponse.json({ url: signedUrl })\n } catch (err) {\n console.log(\'error\')\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n另外,还实现了下载:
\nimport { GetObjectCommand } from \'@aws-sdk/client-s3\'\nimport chalk from \'chalk\'\n\nimport { r2 } from \'@/lib/r2\'\n\nexport async function GET() {\n try {\n console.log(chalk.yellow(`Retrieving pdf from R2!`))\n\n const pdf = await r2.send(\n new GetObjectCommand({\n Bucket: process.env.R2_BUCKET_NAME,\n Key: \'filename.pdf\',\n })\n )\n\n if (!pdf) {\n throw new Error(\'pdf not found.\')\n }\n\n return new Response(pdf.Body?.transformToWebStream(), {\n headers: {\n \'Content-Type\': \'application/pdf\',\n },\n })\n } catch (err) {\n console.log(\'error\', err)\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\nconst handleDownload = async () => {\n const response = await fetch(\'/api/download\')\n const blob = await response.blob()\n const fileURL = window.URL.createObjectURL(blob)\n let anchor = document.createElement(\'a\')\n anchor.href = fileURL\n anchor.download = \'filename.pdf\'\n anchor.click()\n}\n\n// add below upload button\n<button\n type="button"\n className="rounded-md bg-pink-500 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-pink-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-pink-500"\n onClick={handleDownload}\n>\n Download\n</button>\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
1555 次 |
最近记录: |