准备工作:
cloudflare账号1
pinata_api1(申请即可)
操作流程:
1、打开CF创建workers
2、点击右上角编辑代码
3、复制以下代码块粘贴至workers项目内(修改line202-203中的pinata_api)
修改项:
1、新增上传图片网关失效自动切换
2、访问网关源修改为支持大陆地区(谢谢站内其他小伙伴提供的公开网关)
ps:由于是心血来潮,基于chatgpt码出来的;整体美观度不够 还请勿喷
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const url = new URL(request.url)
// 判断是否是上传请求
if (url.pathname === '/upload' && request.method === 'POST') {
const formData = await request.formData()
const imageFile = formData.get('image')
if (imageFile) {
const cid = await uploadToIPFSWithFallback(imageFile)
if (cid) {
return new Response(`<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>图片上传成功</title>
<style>
body {
font-family: 'Arial', sans-serif;
background-color: #ffffff;
margin: 0;
padding: 0;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
background-color: #ffffff;
border-radius: 15px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
padding: 30px;
max-width: 600px;
width: 100%;
margin: 20px;
}
h1 {
color: #2c3e50;
margin-bottom: 20px;
font-size: 2.5em;
}
p {
font-size: 1.2em;
color: #34495e;
}
a {
color: #3498db;
text-decoration: none;
font-weight: bold;
}
a:hover {
text-decoration: underline;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 15px 30px;
border-radius: 8px;
cursor: pointer;
font-size: 1em;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #2980b9;
}
input[type="file"] {
margin: 20px 0;
border: 1px solid #ddd;
border-radius: 5px;
padding: 10px;
background-color: #f9f9f9;
}
</style>
</head>
<body>
<div class="container">
<h1>上传成功!</h1>
<p>CID: ${cid}</p>
<p>访问图片/视频:<a href="https://i0.img2ipfs.com/ipfs/${cid}" target="_blank">点击查看图片/视频</a></p>
</div>
</body>
</html>`, {
headers: { 'content-type': 'text/html; charset=utf-8' },
})
} else {
return new Response('图片/视频上传失败', { status: 500 })
}
}
return new Response('未找到图片/视频', { status: 400 })
}
// 返回美化后的 HTML 上传表单
return new Response(`<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>爱跑路的图床</title>
<style>
body {
font-family: 'Arial', sans-serif;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
transition: background-image 1s ease-in-out;
}
.container {
background-color: rgba(255, 255, 255, 0.9);
border-radius: 15px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
padding: 30px;
max-width: 600px;
width: 100%;
text-align: center;
}
h1 {
color: #2c3e50;
margin-bottom: 20px;
font-size: 2.5em;
}
input[type="file"] {
margin: 20px 0;
border: 1px solid #ddd;
border-radius: 5px;
padding: 10px;
background-color: #f9f9f9;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 15px 30px;
border-radius: 8px;
cursor: pointer;
font-size: 1em;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #2980b9;
}
</style>
<script>
function changeBackground() {
const images = [
'https://source.unsplash.com/random?landscape',
'https://source.unsplash.com/random?nature',
'https://source.unsplash.com/random?mountain',
'https://source.unsplash.com/random?sea'
];
const randomImage = images[Math.floor(Math.random() * images.length)];
document.body.style.backgroundImage = \`url('\${randomImage}')\`;
}
setInterval(changeBackground, 10000); // 每 10 秒更换一次背景图
document.addEventListener('DOMContentLoaded', changeBackground);
</script>
</head>
<body>
<div class="container">
<h1>爱跑路的图床</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="image" accept="image/*" required>
<button type="submit">上传图片/视频</button>
</form>
</div>
</body>
</html>`, {
headers: { 'content-type': 'text/html; charset=utf-8' },
})
}
// 使用多个 IPFS 网关上传图片,并在失败时自动切换
async function uploadToIPFSWithFallback(file) {
const gateways = [
{ url: 'https://api.pinata.cloud/pinning/pinFileToIPFS', headers: {
'pinata_api_key': 'XXXXX',
'pinata_secret_api_key': 'XXXXX'
}},
{ url: 'https://gateway.ipfs.io/api/v0/add' },
{ url: 'https://api.infura.io:5001/api/v0/add' },
{ url: 'https://ipfs.siliconvalley.social/api/v0/add' },
{ url: 'https://cloudflare-ipfs.com/api/v0/add' },
{ url: 'https://dweb.link/api/v0/add' },
{ url: 'https://ipfs.eth.aragon.network/api/v0/add' },
{ url: 'https://nftstorage.link/api/v0/add' },
{ url: 'https://4everland.io/api/v0/add' },
{ url: 'https://ipfs.cyou/api/v0/add' },
{ url: 'https://storry.tv/api/v0/add' },
{ url: 'https://hardbin.com/api/v0/add' },
{ url: 'https://ipfs.runfission.com/api/v0/add' },
{ url: 'https://w3s.link/api/v0/add' },
{ url: 'https://trustless-gateway.link/api/v0/add' },
{ url: 'https://ipfs.ipfs.tech/api/v0/add' },
{ url: 'https://gateway.ipfs.btcscan.org/api/v0/add' },
{ url: 'https://i0.img2ipfs.com/api/v0/add' },
{ url: 'https://ipfs.crossbell.io/api/v0/add' },
{ url: 'https://gateway.ipfsscan.io/api/v0/add' }
]
for (const gateway of gateways) {
try {
const cid = await uploadToIPFS(file, gateway.url, gateway.headers || {})
if (cid) {
return cid
}
} catch (error) {
console.error(`上传到 ${gateway.url} 失败:`, error)
}
}
return null // 如果所有网关都失败,返回 null
}
async function uploadToIPFS(file, url, headers) {
const formData = new FormData()
formData.append('file', file, 'image.png') // 确保文件名存在
const response = await fetch(url, {
method: 'POST',
headers: headers,
body: formData
})
if (response.ok) {
const data = await response.json()
return data.IpfsHash || data.Hash // 返回上传文件的 CID
} else {
console.error('上传失败', await response.text()) // 输出错误日志
throw new Error('上传失败')
}
}
© 版权声明
THE END
暂无评论内容