WARNING:R2免费容量是10G,Workers免费访问限制是每日100万次,很容易被刷流量,请为你绑定的域名设置速率限制等限制手段以避免睡一晚上成为百万负翁
创建一个R2存储桶
- 不教了,简单的雅痞。可见创建R2存储桶
将R2与Workers连接起来
- 不教了,简单的雅痞。可见创建 Workers,连接 R2
- 将Workers代码改为如下,设置一个目录单独存放要公开的文件,这里是
guest
。代码内嵌了HTML,可自行更改:
export default {
async fetch(request, env, ctx) {
const bucket = env.MY_BUCKET;
const rootDirectory = 'guest/';
const url = new URL(request.url);
// Helper function to get the current directory
const getCurrentDirectory = (path) => {
const cleanPath = path.replace(/^\/+|\/+$/g, '');
return rootDirectory + cleanPath + (cleanPath ? '/' : '');
};
// Helper function to get parent directory
const getParentDirectory = (path) => {
const parts = path.split('/').filter(p => p);
parts.pop();
return '/' + parts.join('/');
};
// List files and folders in the current directory
async function listDirectory(directory) {
const objects = await bucket.list({ prefix: directory, delimiter: '/' });
const items = new Set();
for (const obj of objects.objects) {
const relativePath = obj.key.slice(directory.length);
if (relativePath) {
items.add(relativePath.split('/')[0]);
}
}
for (const prefix of objects.delimitedPrefixes) {
const relativePath = prefix.slice(directory.length);
if (relativePath) {
items.add(relativePath.split('/')[0]);
}
}
return Array.from(items).sort();
}
// Handle directory listing
if (!url.pathname.startsWith('/download/')) {
const currentDirectory = getCurrentDirectory(url.pathname);
try {
const items = await listDirectory(currentDirectory);
let html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AcoFork R2 Files</title>
<style>
body, html {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
line-height: 1.6;
height: 100%;
}
body {
background-image: url('https://hrandom.onani.cn');
background-size: cover;
background-position: center;
background-attachment: fixed;
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 80%;
max-width: 800px;
margin: 40px;
padding: 30px;
background-color: rgba(255, 255, 255, 0.5);
backdrop-filter: blur(10px);
border-radius: 15px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
h1 {
color: #333;
text-align: center;
margin-bottom: 30px;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
}
li {
margin-bottom: 10px;
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
transition: all 0.3s ease;
}
li:hover {
transform: translateY(-3px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
a {
display: block;
padding: 12px 15px;
text-decoration: none;
color: #333;
transition: background-color 0.3s ease;
}
a:hover {
background-color: rgba(255, 255, 255, 0.5);
}
.folder::before {
content: "📁 ";
color: #FFA500;
}
.file::before {
content: "📄 ";
color: #008000;
}
.parent-link {
display: inline-block;
margin-bottom: 20px;
padding: 8px 15px;
background-color: rgba(0, 102, 204, 0.8);
color: white;
text-decoration: none;
border-radius: 5px;
transition: background-color 0.3s ease;
}
.parent-link:hover {
background-color: rgba(0, 82, 163, 0.9);
}
@keyframes clickEffect {
0% { transform: scale(1); }
50% { transform: scale(0.95); }
100% { transform: scale(1); }
}
.click-effect {
animation: clickEffect 0.3s;
}
</style>
</head>
<body>
<div class="container">
<h1>我的 R2 Files</h1>
`;
// Add parent directory link if not in root
if (currentDirectory !== rootDirectory) {
const parentDir = getParentDirectory(url.pathname);
html += `<a href="${parentDir}" class="parent-link">← Parent Directory</a>`;
}
html += '<ul>';
for (const item of items) {
const itemPath = currentDirectory.slice(rootDirectory.length) + item;
const isFolder = !item.includes('.');
const className = isFolder ? 'folder' : 'file';
// Update href for files to use the external download URL
const href = isFolder
? `/${encodeURIComponent(itemPath)}`
: `https://r2-dl.afo.im/guest/${encodeURIComponent(itemPath)}`;
html += `<li class="${className}"><a href="${href}" onclick="this.classList.add('click-effect'); setTimeout(() => this.classList.remove('click-effect'), 300);">${item}${isFolder ? '/' : ''}</a></li>`;
}
html += `
</ul>
</div>
<script>
document.addEventListener('DOMContentLoaded', (event) => {
document.querySelectorAll('a').forEach(link => {
link.addEventListener('click', function(e) {
if (!this.classList.contains('parent-link')) {
e.preventDefault();
this.classList.add('click-effect');
setTimeout(() => {
window.location = this.href;
}, 300);
}
});
});
});
</script>
</body>
</html>`;
return new Response(html, {
headers: { 'Content-Type': 'text/html; charset=utf-8' },
});
} catch (error) {
console.error('Error listing objects:', error);
return new Response('Error listing objects', { status: 500 });
}
}
// Default response for any other invalid requests
return new Response('Invalid request', { status: 400 });
},
};
- 如何上传文件见为你的存储桶添加文件