因为R2要绑定信用卡,不适合多账号无线创建,因此,本文教你一键将cfworker(KV)变成小文件云储存器
目标计划:
分片储存大文件
注意:CF规则里好像有禁止储存流媒体,为避免封号,不要存视频,大图等想作死小图还是可以的
注意,只能储存小文件,太大会报413错误!
第一步:创建worker
第二步,绑定KV_FILE到worker
第三部,根据实际情况写入以下代码:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
const ACCESS_CODE = "workerkvfile";
const KV_NAMESPACE = KV_FILE;
async function handleRequest(request) {
const url = new URL(request.url);
const path = url.pathname.split("/")[1];
const accesscode = url.searchParams.get("accesscode");
if (accesscode !== ACCESS_CODE) {
return new Response("Invalid access code.", { status: 403 });
}
switch (path) {
case "upload":
return uploadFile(request);
case "fetch":
const id = url.searchParams.get("id");
return fetchFile(id);
case "delete":
const deleteId = url.searchParams.get("id");
return deleteFile(deleteId);
default:
return new Response("Invalid request.", { status: 400 });
}
}
async function uploadFile(request) {
// 检查Content-Type是否为multipart/form-data
const contentType = request.headers.get("content-type") || "";
if (!contentType.includes("multipart/form-data")) {
return new Response("Unsupported file type.", { status: 400 });
}
// 使用FormData解析文件数据
const formData = await request.formData();
const file = formData.get("file");
if (!file) {
return new Response("File not found in request.", { status: 400 });
}
// 转换为二进制数据
const arrayBuffer = await file.arrayBuffer();
const id = crypto.randomUUID();
// 存储文件
await KV_NAMESPACE.put(id, arrayBuffer, { metadata: { contentType: file.type } });
return new Response(id, {
status: 200,
headers: {
"Content-Type": "text/plain",
},
});
}
async function fetchFile(id) {
const fileData = await KV_NAMESPACE.getWithMetadata(id, "arrayBuffer");
if (!fileData.value) {
return new Response("File not found.", { status: 404 });
}
// 直接以二进制形式返回文件数据和正确的Content-Type
return new Response(fileData.value, {
status: 200,
headers: {
"Content-Type": fileData.metadata.contentType || "application/octet-stream",
},
});
}
async function deleteFile(id) {
await KV_NAMESPACE.delete(id);
return new Response("File deleted successfully.", { status: 200 });
}
accececode可修改
无限空间教程:
先搞个无限邮箱:
https://zhile.io/2023/12/09/pandoranext-introduction.html
无限注册账号,每个账号有IGB,不够用的时候就加。
附:调用示例:
python
import requests
# Worker的基础URL
BASE_URL = "你的部署URL"
# 预设的访问码
ACCESS_CODE = "workerkvfile"
def upload_file(file_path):
"""上传文件到Worker"""
files = {'file': open(file_path, 'rb')}
response = requests.post(f"{BASE_URL}/upload?accesscode={ACCESS_CODE}", files=files)
if response.status_code == 200:
return response.text
else:
print("上传失败:", response.text)
return None
def fetch_file(file_id, save_path):
"""从Worker下载文件"""
response = requests.get(f"{BASE_URL}/fetch?id={file_id}&accesscode={ACCESS_CODE}")
if response.status_code == 200:
with open(save_path, 'wb') as f:
f.write(response.content)
print("文件下载成功")
else:
print("下载失败:", response.text)
def delete_file(file_id):
"""从Worker删除文件"""
response = requests.get(f"{BASE_URL}/delete?id={file_id}&accesscode={ACCESS_CODE}")
if response.status_code == 200:
print("文件删除成功")
else:
print("删除失败:", response.text)
if __name__ == "__main__":
# 文件路径
file_path = "test.jpg"
save_path = "downloaded_test.jpg"
# 上传文件
print("正在上传文件...")
file_id = upload_file(file_path)
if file_id:
print(f"文件上传成功,ID: {file_id}")
# 下载文件
print("正在下载文件...")
fetch_file(file_id, save_path)
# 删除文件
print("正在删除文件...")
delete_file(file_id)