mirror of
https://github.com/ElmGates/Cloudflare-img2url.git
synced 2026-01-12 04:54:55 +08:00
first commit
This commit is contained in:
155
index.js
Normal file
155
index.js
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* Cloudflare Worker 图片上传服务
|
||||
* 接收 JSON 格式的 base64 编码图片,上传到 R2 存储桶,并返回图片链接
|
||||
*/
|
||||
|
||||
export default {
|
||||
async fetch(request, env, ctx) {
|
||||
// 只允许 POST 请求
|
||||
if (request.method !== 'POST') {
|
||||
return new Response('只接受 POST 请求', { status: 405 });
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取请求体内容并解析 JSON
|
||||
const contentType = request.headers.get('content-type') || '';
|
||||
|
||||
if (!contentType.includes('application/json')) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: '请求头必须包含 Content-Type: application/json'
|
||||
}), {
|
||||
status: 400,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 解析 JSON 请求体
|
||||
let jsonData;
|
||||
try {
|
||||
jsonData = await request.json();
|
||||
} catch (e) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: '无效的 JSON 格式'
|
||||
}), {
|
||||
status: 400,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 支持嵌套的 img 对象
|
||||
if (jsonData.img) {
|
||||
jsonData = jsonData.img;
|
||||
}
|
||||
|
||||
// 检查 JSON 中是否包含必要字段
|
||||
if (!jsonData || !jsonData.imageData) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: 'JSON 必须包含 imageData 字段'
|
||||
}), {
|
||||
status: 400,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 获取图片类型,默认为 jpeg
|
||||
const imageType = jsonData.imageType || 'jpeg';
|
||||
// 清理 base64 字符串中的换行符和空格
|
||||
const imageData = jsonData.imageData.replace(/[\r\n\s]/g, '');
|
||||
|
||||
// 验证 base64 数据是否有效 (修改后的验证方法)
|
||||
if (!isValidBase64(imageData)) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: '请提供有效的 base64 编码数据'
|
||||
}), {
|
||||
status: 400,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// 生成唯一的文件名
|
||||
const fileName = generateUniqueFileName(imageType);
|
||||
|
||||
// 将 base64 解码为二进制数据
|
||||
const binaryData = base64ToArrayBuffer(imageData);
|
||||
|
||||
// 上传到 R2 存储桶
|
||||
await env.MY_BUCKET.put(fileName, binaryData, {
|
||||
httpMetadata: {
|
||||
contentType: `image/${imageType}`,
|
||||
},
|
||||
});
|
||||
|
||||
// 构建图片 URL
|
||||
const imageUrl = `${env.PUBLIC_URL}/${fileName}`;
|
||||
|
||||
// 返回成功响应
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
url: imageUrl,
|
||||
message: '图片上传成功'
|
||||
}), {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
// 处理错误
|
||||
console.error('上传过程中出错:', error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: '上传失败: ' + error.message
|
||||
}), {
|
||||
status: 500,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查字符串是否为有效的 base64 编码
|
||||
*/
|
||||
function isValidBase64(str) {
|
||||
try {
|
||||
// 检查是否为有效的 base64 字符串
|
||||
const base64Regex = /^[A-Za-z0-9+/=]+$/;
|
||||
return base64Regex.test(str);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一的文件名
|
||||
*/
|
||||
function generateUniqueFileName(imageType) {
|
||||
const timestamp = Date.now();
|
||||
const randomString = Math.random().toString(36).substring(2, 10);
|
||||
return `${timestamp}-${randomString}.${imageType}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 base64 字符串转换为 ArrayBuffer
|
||||
*/
|
||||
function base64ToArrayBuffer(base64) {
|
||||
const binaryString = atob(base64);
|
||||
const bytes = new Uint8Array(binaryString.length);
|
||||
for (let i = 0; i < binaryString.length; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
}
|
||||
188
readme.md
Normal file
188
readme.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# Cloudflare Worker 图片上传服务
|
||||
|
||||
这是一个基于 Cloudflare Worker 的图片上传服务,可以接收 base64 编码的图片,将其上传到 Cloudflare R2 存储桶中,并返回可访问的图片链接,在用量不大时是完全免费的!
|
||||
|
||||
## 功能特点
|
||||
|
||||
- 接收 JSON 格式的 base64 编码图片
|
||||
- 支持多种图片格式(JPEG、PNG、GIF、WebP 等)
|
||||
- 自动生成唯一文件名
|
||||
- 返回可直接访问的图片链接
|
||||
- 支持苹果快捷指令等客户端工具
|
||||
|
||||
## 部署指南
|
||||
|
||||
### 前提条件
|
||||
|
||||
1. 拥有 Cloudflare 账户
|
||||
2. 已创建 Cloudflare R2 存储桶(github和bing上教程太多了,这里就不一一说明了)
|
||||
3. 安装 Wrangler CLI 工具
|
||||
|
||||
### 安装 Wrangler CLI
|
||||
|
||||
```bash
|
||||
npm install -g wrangler
|
||||
```
|
||||
|
||||
### 登录到 Cloudflare 账户
|
||||
|
||||
```bash
|
||||
wrangler login
|
||||
```
|
||||
|
||||
### 配置 wrangler.toml
|
||||
|
||||
修改项目根目录下的 `wrangler.toml` 文件:
|
||||
|
||||
```toml
|
||||
name = "image-uploader"
|
||||
main = "index.js"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
# 配置 R2 存储桶
|
||||
[[r2_buckets]]
|
||||
binding = "MY_BUCKET"
|
||||
bucket_name = "your-bucket-name" # 替换为您的 R2 存储桶名称
|
||||
|
||||
# 环境变量
|
||||
[vars]
|
||||
PUBLIC_URL = "https://your-bucket-public-url" # 替换为您的 R2 存储桶公共访问 URL
|
||||
```
|
||||
|
||||
请确保将 `bucket_name` 替换为您实际创建的 R2 存储桶名称,并将 `PUBLIC_URL` 替换为您的 R2 存储桶公共访问 URL。
|
||||
|
||||
### 部署 Worker
|
||||
|
||||
```bash
|
||||
wrangler deploy
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
### API 接口
|
||||
|
||||
- **URL**: 您的 Worker URL(部署后获得)
|
||||
- **方法**: POST
|
||||
- **请求头**:
|
||||
```
|
||||
Content-Type: application/json
|
||||
```
|
||||
- **请求体**:
|
||||
```json
|
||||
{
|
||||
"imageType": "jpeg",
|
||||
"imageData": "base64编码的图片数据"
|
||||
}
|
||||
```
|
||||
|
||||
或者使用嵌套格式:
|
||||
|
||||
```json
|
||||
{
|
||||
"img": {
|
||||
"imageType": "jpeg",
|
||||
"imageData": "base64编码的图片数据"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **参数说明**:
|
||||
- `imageType`: 图片类型(如 jpeg, png, gif 等),如果未提供则默认为 jpeg
|
||||
- `imageData`: base64 编码的图片数据(不包含 `data:image/xxx;base64,` 前缀)
|
||||
|
||||
- **响应**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"url": "https://your-bucket-public-url/timestamp-randomstring.jpeg",
|
||||
"message": "图片上传成功"
|
||||
}
|
||||
```
|
||||
|
||||
### 在苹果快捷指令中使用
|
||||
|
||||
1. 创建新的快捷指令
|
||||
2. 添加"选取照片"操作
|
||||
3. 添加"编码媒体"操作,设置编码格式为"Base64"
|
||||
4. 最好添加一个调整图片大小的操作,以减少图片大小。
|
||||
5. 添加"获取网页内容"操作:
|
||||
- URL: 您的 Worker URL
|
||||
- 方法: POST
|
||||
- 请求头部: Content-Type: application/json
|
||||
- 请求正文: JSON 格式,包含以下字段:
|
||||
```json
|
||||
{
|
||||
"imageType": "jpeg",
|
||||
"imageData": "{{输入}}"
|
||||
}
|
||||
```
|
||||
6. 添加"获取词典中的值"操作,提取响应中的 URL
|
||||
7. 添加"显示结果"或"复制到剪贴板"操作
|
||||
|
||||
### 在其他客户端中使用
|
||||
|
||||
#### cURL
|
||||
|
||||
```bash
|
||||
curl -X POST https://your-worker-url.workers.dev \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"imageType":"jpeg","imageData":"base64编码的图片数据"}'
|
||||
```
|
||||
|
||||
#### JavaScript
|
||||
|
||||
```javascript
|
||||
const imageData = 'base64编码的图片数据';
|
||||
|
||||
fetch('https://your-worker-url.workers.dev', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
imageType: 'jpeg',
|
||||
imageData: imageData
|
||||
})
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => console.log(data.url))
|
||||
.catch(error => console.error('Error:', error));
|
||||
```
|
||||
|
||||
#### Python
|
||||
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
|
||||
image_data = 'base64编码的图片数据'
|
||||
|
||||
response = requests.post(
|
||||
'https://your-worker-url.workers.dev',
|
||||
headers={'Content-Type': 'application/json'},
|
||||
data=json.dumps({
|
||||
'imageType': 'jpeg',
|
||||
'imageData': image_data
|
||||
})
|
||||
)
|
||||
|
||||
print(response.json()['url'])
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 对于大图片,建议在客户端进行压缩后再上传,以避免超出 Cloudflare Worker 的处理限制
|
||||
2. 确保您的 R2 存储桶已正确配置公共访问权限
|
||||
3. 为了增强安全性,您可能需要添加身份验证机制
|
||||
4. 如果 base64 字符串包含换行符(如苹果设备生成的),服务会自动清理,但是最好不要有此类内容
|
||||
|
||||
|
||||
## 贡献
|
||||
|
||||
欢迎通过 Issues 和 Pull Requests 提供反馈和改进建议。
|
||||
|
||||
## 联系方式
|
||||
|
||||
如有问题,请通过 GitHub Issues 联系我们。
|
||||
|
||||
|
||||
12
wrangler.toml
Normal file
12
wrangler.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
name = "image-uploader"
|
||||
main = "index.js"
|
||||
compatibility_date = "2025-01-01"
|
||||
|
||||
# 配置 R2 存储桶
|
||||
[[r2_buckets]]
|
||||
binding = "MY_BUCKET"
|
||||
bucket_name = "your-bucket-name"
|
||||
|
||||
# 环境变量
|
||||
[vars]
|
||||
PUBLIC_URL = "https://your-bucket-public-url"
|
||||
Reference in New Issue
Block a user