Pages通过Git存储库部署,Workers通过API Key访问你的Github仓库目录开放查询API,Pages读取这个API,展示文件
file
文件夹,后续的文件上传下载都在这个文件夹index.html
,填写代码:const response = await fetch('https://file-up.afo.im/list');
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File List</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
}
ul {
list-style-type: none;
padding: 0;
}
li {
margin: 5px 0;
}
a {
text-decoration: none;
color: #007bff;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>File List</h1>
<ul id="file-list"></ul>
<script>
async function fetchFileList() {
try {
const response = await fetch('https://file-up.afo.im/list');
if (!response.ok) {
throw new Error('Failed to fetch file list');
}
const fileList = await response.text();
const files = fileList.split('\n').filter(file => file.trim() !== '');
displayFiles(files);
} catch (error) {
console.error('Error fetching file list:', error);
document.getElementById('file-list').innerHTML = '<li>Error fetching file list</li>';
}
}
function displayFiles(files) {
const fileListElement = document.getElementById('file-list');
fileListElement.innerHTML = files.map(file =>
`<li><a href="/file/${encodeURIComponent(file)}">${file}</a></li>`
).join('');
}
fetchFileList();
</script>
</body>
</html>
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const url = new URL(request.url)
const path = url.pathname
if (path === '/') {
return addCORSHeaders(showLoginForm())
} else if (path === '/login') {
return addCORSHeaders(await handleLogin(request))
} else if (path === '/upload') {
return addCORSHeaders(await handleUpload(request))
} else if (path === '/check-config') {
return addCORSHeaders(await checkConfig())
} else if (path === '/list') {
return addCORSHeaders(await listFiles()) // 允许直接访问 /list,无需授权
} else {
return addCORSHeaders(new Response('Not Found', { status: 404 }))
}
}
function showLoginForm() {
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<form action="/login" method="POST">
<input type="password" name="password" placeholder="Enter password" required>
<button type="submit">Login</button>
</form>
<p><a href="/check-config">Check server configuration</a></p>
</body>
</html>
`
return new Response(html, {
headers: { 'Content-Type': 'text/html' }
})
}
async function handleLogin(request) {
const formData = await request.formData()
const password = formData.get('password')
if (password === PASSWORD) {
return showUploadForm()
} else {
return new Response('Invalid password', { status: 401 })
}
}
function showUploadForm() {
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="file" required>
<button type="submit">Upload</button>
</form>
</body>
</html>
`
return new Response(html, {
headers: { 'Content-Type': 'text/html' }
})
}
async function handleUpload(request) {
try {
const formData = await request.formData()
const file = formData.get('file')
if (!file) {
return new Response('No file uploaded', { status: 400 })
}
const content = await file.arrayBuffer()
const encodedContent = btoa(String.fromCharCode.apply(null, new Uint8Array(content)))
const githubResponse = await fetch(`https://api.github.com/repos/${GITHUB_REPO}/contents/file/${file.name}`, {
method: 'PUT',
headers: {
'Authorization': `token ${GITHUB_TOKEN}`,
'Content-Type': 'application/json',
'User-Agent': 'Cloudflare Worker'
},
body: JSON.stringify({
message: `Upload ${file.name}`,
content: encodedContent
})
})
if (githubResponse.ok) {
return new Response('File uploaded successfully', { status: 200 })
} else {
const errorData = await githubResponse.text()
console.error('GitHub API Error:', errorData)
return new Response(`Failed to upload file: ${errorData}`, { status: 500 })
}
} catch (error) {
console.error('Upload error:', error)
return new Response(`Error during upload: ${error.message}`, { status: 500 })
}
}
async function listFiles() {
try {
const githubResponse = await fetch(`https://api.github.com/repos/${GITHUB_REPO}/contents/file`, {
headers: {
'Authorization': `token ${GITHUB_TOKEN}`,
'User-Agent': 'Cloudflare Worker'
}
})
if (!githubResponse.ok) {
const errorData = await githubResponse.text()
console.error('GitHub API Error:', errorData)
return new Response(`Failed to fetch file list: ${errorData}`, { status: 500 })
}
const files = await githubResponse.json()
// 将文件名转换为纯文本,一行一个
const fileNames = files.map(file => file.name).join('\n')
return new Response(fileNames, {
headers: { 'Content-Type': 'text/plain' }
})
} catch (error) {
console.error('Error fetching files:', error)
return new Response(`Error during fetching files: ${error.message}`, { status: 500 })
}
}
async function checkConfig() {
let configStatus = 'All configurations are set correctly.'
if (!PASSWORD) {
configStatus = 'ERROR: PASSWORD is not set.'
} else if (!GITHUB_TOKEN) {
configStatus = 'ERROR: GITHUB_TOKEN is not set.'
} else if (!GITHUB_REPO) {
configStatus = 'ERROR: GITHUB_REPO is not set.'
} else {
try {
const response = await fetch(`https://api.github.com/repos/${GITHUB_REPO}`, {
headers: {
'Authorization': `token ${GITHUB_TOKEN}`,
'User-Agent': 'Cloudflare Worker'
}
})
const responseText = await response.text()
if (!response.ok) {
try {
const data = JSON.parse(responseText)
configStatus = `ERROR: GitHub API returned an error: ${data.message}`
} catch (jsonError) {
configStatus = `ERROR: GitHub API returned a non-JSON response. Status: ${response.status}, Body: ${responseText.substring(0, 100)}...`
}
} else {
try {
JSON.parse(responseText)
configStatus += ' GitHub connection successful.'
} catch (jsonError) {
configStatus = `WARNING: GitHub API returned a non-JSON response, but the connection was successful. Status: ${response.status}, Body: ${responseText.substring(0, 100)}...`
}
}
} catch (error) {
configStatus = `ERROR: Failed to connect to GitHub API: ${error.message}`
}
}
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Configuration Check</title>
</head>
<body>
<h1>Configuration Check</h1>
<p>${configStatus}</p>
<a href="/">Back to Login</a>
</body>
</html>
`
return new Response(html, {
status: 200,
headers: { 'Content-Type': 'text/html' }
})
}
// 添加 CORS 头
function addCORSHeaders(response) {
const headers = new Headers(response.headers)
headers.set('Access-Control-Allow-Origin', '*')
headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, OPTIONS')
headers.set('Access-Control-Allow-Headers', 'Content-Type')
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers
})
}
为Workers添加变量
GITHUB_REPO
格式为:Github用户名/Github仓库名
GITHUB_TOKEN
格式为:你的Github API Key
。需要有仓库(Repository)修改权限
PASSWORD
为访问上传端点的密码,自行设置(更建议使用Git上传)
访问你的自定义域的/list
,看看查询API是否正常,是否能列出仓库下file文件夹下的文件,如
const response = await fetch('https://file-up.afo.im/list');
替换https://file-up.afo.im/list
为你的
不教了,简单的雅痞。可见教你搭建你的第一个网站!无需服务器即可上手!注意要用Git存储库部署而不是本地部署
Cloudflare Pages当有提交时会自动重新部署,实现新文件自动更新