{"id":21583143,"url":"https://github.com/caomeiyouren/sharp-cloud-uploader","last_synced_at":"2026-05-05T08:31:28.493Z","repository":{"id":264224631,"uuid":"892702701","full_name":"CaoMeiYouRen/sharp-cloud-uploader","owner":"CaoMeiYouRen","description":"一个使用 sharp 进行图片压缩，并上传文件到 R2、S3 或 Vercel Blob 的云函数。支持 Vercel Functions/Cloudflare Workers/Docker 等方式部署。","archived":false,"fork":false,"pushed_at":"2026-01-31T20:20:50.000Z","size":1750,"stargazers_count":1,"open_issues_count":12,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-01T08:04:13.966Z","etag":null,"topics":["amazon-s3","cloudflare-r2","docker","nodejs","vercel-serverless-functions"],"latest_commit_sha":null,"homepage":"https://github.com/CaoMeiYouRen/sharp-cloud-uploader","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CaoMeiYouRen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-11-22T16:01:23.000Z","updated_at":"2026-01-31T20:20:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"d00bbee1-9a71-42cb-9604-569704f60391","html_url":"https://github.com/CaoMeiYouRen/sharp-cloud-uploader","commit_stats":null,"previous_names":["caomeiyouren/sharp-cloud-uploader"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/CaoMeiYouRen/sharp-cloud-uploader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaoMeiYouRen%2Fsharp-cloud-uploader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaoMeiYouRen%2Fsharp-cloud-uploader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaoMeiYouRen%2Fsharp-cloud-uploader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaoMeiYouRen%2Fsharp-cloud-uploader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CaoMeiYouRen","download_url":"https://codeload.github.com/CaoMeiYouRen/sharp-cloud-uploader/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaoMeiYouRen%2Fsharp-cloud-uploader/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32641992,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"online","status_checked_at":"2026-05-05T02:00:06.033Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amazon-s3","cloudflare-r2","docker","nodejs","vercel-serverless-functions"],"created_at":"2024-11-24T14:18:16.609Z","updated_at":"2026-05-05T08:31:28.488Z","avatar_url":"https://github.com/CaoMeiYouRen.png","language":"TypeScript","funding_links":["https://patreon.com/CaoMeiYouRen"],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003esharp-cloud-uploader \u003c/h1\u003e\n\u003cp\u003e\n  \u003cimg alt=\"Version\" src=\"https://img.shields.io/github/package-json/v/CaoMeiYouRen/sharp-cloud-uploader.svg\" /\u003e\n  \u003ca href=\"https://hub.docker.com/r/caomeiyouren/sharp-cloud-uploader\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Docker Pulls\" src=\"https://img.shields.io/docker/pulls/caomeiyouren/sharp-cloud-uploader\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/CaoMeiYouRen/sharp-cloud-uploader/actions?query=workflow%3ARelease\" target=\"_blank\"\u003e\n    \u003cimg alt=\"GitHub Workflow Status\" src=\"https://img.shields.io/github/actions/workflow/status/CaoMeiYouRen/sharp-cloud-uploader/release.yml?branch=master\"\u003e\n  \u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/node-%3E%3D18-blue.svg\" /\u003e\n  \u003ca href=\"https://github.com/CaoMeiYouRen/sharp-cloud-uploader#readme\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Documentation\" src=\"https://img.shields.io/badge/documentation-yes-brightgreen.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/CaoMeiYouRen/sharp-cloud-uploader/graphs/commit-activity\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Maintenance\" src=\"https://img.shields.io/badge/Maintained%3F-yes-green.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/CaoMeiYouRen/sharp-cloud-uploader/blob/master/LICENSE\" target=\"_blank\"\u003e\n    \u003cimg alt=\"License: MIT\" src=\"https://img.shields.io/github/license/CaoMeiYouRen/sharp-cloud-uploader?color=yellow\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003e 一个使用 sharp 进行图片压缩，并上传文件到 R2、S3 或 Vercel Blob 的云函数。支持 Vercel Functions/Cloudflare Workers/Docker 等方式部署。\n\n## 🏠 主页\n\n[https://github.com/CaoMeiYouRen/sharp-cloud-uploader#readme](https://github.com/CaoMeiYouRen/sharp-cloud-uploader#readme)\n\n## 📦 依赖要求\n\n-   node \u003e=18\n\n## 🚀 部署\n\n### Vercel 部署（推荐）\n\n\u003e 如果遇到了接口长时间无响应/超时的问题，请在 Vercel 控制台中将环境变量`NODEJS_HELPERS`设置为 `0` 后，重新部署，再进行测试。\n\n点击以下按钮一键部署到 Vercel。\n\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FCaoMeiYouRen%2Fsharp-cloud-uploader.git)\n\n\u003e 如果使用 `Vercel Blob` 作为存储，请参考 [Vercel Blob](https://vercel.com/docs/storage/vercel-blob) 有关文档。\n\n### Cloudflare Workers 部署\n\n点击下方按钮一键部署到 Cloudflare Workers。\n\n[![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/CaoMeiYouRen/sharp-cloud-uploader)\n\n**注意：由于 Cloudflare Workers 不支持 sharp，所以在 Cloudflare Workers 部署时，图片不会经过 sharp 压缩，仅转存原图。**\n\n\u003e 如果想存储到 R2，请将 `STORAGE` 设置为 `r2`，并修改 wrangler.toml 中的 r2_buckets 相关配置。\n\n### Docker 镜像\n\n支持两种注册表：\n\n-   Docker Hub: [`caomeiyouren/sharp-cloud-uploader`](https://hub.docker.com/r/caomeiyouren/sharp-cloud-uploader)\n-   GitHub: [`ghcr.io/caomeiyouren/sharp-cloud-uploader`](https://github.com/CaoMeiYouRen/sharp-cloud-uploader/pkgs/container/sharp-cloud-uploader)\n\n支持以下架构：\n\n-   `linux/amd64`\n-   `linux/arm64`\n\n有以下几种 tags：\n\n| Tag            | 描述     | 举例          |\n| :------------- | :------- | :------------ |\n| `latest`       | 最新     | `latest`      |\n| `{YYYY-MM-DD}` | 特定日期 | `2024-06-07`  |\n| `{sha-hash}`   | 特定提交 | `sha-0891338` |\n| `{version}`    | 特定版本 | `1.2.3`       |\n\n### Docker Compose 部署\n\n下载 [docker-compose.yml](https://github.com/CaoMeiYouRen/sharp-cloud-uploader/blob/master/docker-compose.yml)\n\n```sh\nwget https://raw.githubusercontent.com/CaoMeiYouRen/sharp-cloud-uploader/refs/heads/master/docker-compose.yml\n```\n\n检查有无需要修改的配置\n\n```sh\nvim docker-compose.yml  # 也可以是你喜欢的编辑器\n```\n\n\u003e 在公网部署时建议设置 AUTH_TOKEN 环境变量，以避免被他人滥用。\n\u003e\n\u003e 请修改 docker-compose.yml 文件中的 environment 字段修改环境变量。\n\n启动\n\n```sh\ndocker-compose up -d\n```\n\n在浏览器中打开 `http://{Server IP}:3000` 即可查看结果\n\n### Node.js 部署\n\n确保本地已安装 Node.js 和 pnpm。\n\n```sh\n# 下载源码\ngit clone https://github.com/CaoMeiYouRen/sharp-cloud-uploader.git  --depth=1\ncd sharp-cloud-uploader\n# 安装依赖\npnpm i --frozen-lockfile\n# 构建项目\npnpm build\n# 启动项目\npnpm start\n```\n\n在浏览器中打开 `http://{Server IP}:3000` 即可查看结果\n\n\u003e 请修改 .env 文件修改环境变量。\n\n## 👨‍💻 使用\n\n如果在本地部署，基础路径为 `http://localhost:3000`\n\n在服务器或云函数部署则为 `http(s)://{Server IP}`。\n\n例如：\n\n如果基础路径为 `https://example.vercel.app`，则 `//upload-from-url` 的完整路径为 `https://example.vercel.app/upload-from-url`\n\n### 1. 上传图片接口\n\n#### 1.1 从 URL 上传图片\n\n接口路径: `/upload-from-url`\n\n请求方法: `POST`\n\n请求参数:\n\n-   `url`: 图片的 URL 地址 (必填)\n\n请求示例:\n\n```json\n{\n    \"url\": \"https://example.com/image.jpg\"\n}\n```\n\n响应示例:\n\n```json\n{\n    \"url\": \"https://example.com/bucket-prefix/20231001123456789-abcdefg.jpg\",\n    \"success\": true,\n    \"status\": 200\n}\n```\n\n错误响应示例:\n\n```json\n{\n    \"status\": 400,\n    \"message\": \"URL is required\"\n}\n```\n\n#### 1.2 从请求体上传图片\n\n接口路径: `/upload-from-body`\n\n请求方法: `POST`\n\n请求参数:\n\n-   图片数据: 二进制数据 (必填)\n\n请求示例:\n\n```bash\ncurl -X POST -H \"Content-Type: image/jpeg\" --data-binary @image.jpg http://localhost:3000/upload-from-body\n```\n\n响应示例:\n\n```json\n{\n    \"url\": \"https://example.com/bucket-prefix/20231001123456789-abcdefg.jpg\",\n    \"success\": true,\n    \"status\": 200\n}\n```\n\n错误响应示例:\n\n```json\n{\n    \"status\": 400,\n    \"message\": \"Invalid image format\"\n}\n```\n\n### 2. 代码示例\n\n#### 2.1 使用 fetch 从 URL 上传图片\n\n```ts\nconst uploadFromUrl = async () =\u003e {\n    const url = \"https://example.com/image.jpg\";\n    const response = await fetch(\"http://localhost:3000/upload-from-url\", {\n        method: \"POST\",\n        headers: {\n            \"Content-Type\": \"application/json\",\n        },\n        body: JSON.stringify({ url }),\n    });\n    const data = await response.json();\n    console.log(data);\n};\n\nuploadFromUrl();\n```\n\n#### 2.2 使用 `fetch` 从请求体上传图片\n\n```javascript\nconst uploadFromBody = async () =\u003e {\n    const imageFile = document.getElementById(\"image-file\").files[0];\n    const reader = new FileReader();\n    reader.onload = async () =\u003e {\n        const response = await fetch(\"http://localhost:3000/upload-from-body\", {\n            method: \"POST\",\n            headers: {\n                \"Content-Type\": imageFile.type,\n            },\n            body: reader.result,\n        });\n        const data = await response.json();\n        console.log(data);\n    };\n    reader.readAsArrayBuffer(imageFile);\n};\n\nuploadFromBody();\n```\n\n### 环境变量配置\n\n请参考 [.env](./src/.env) 文件中的注释。\n\n```ini\n# 运行端口\nPORT=3000\n\n# 超时时间(ms)\n# 如果在 vercel 中运行，则还要修改 vercel.json 中的 maxDuration 字段(单位：秒)\nTIMEOUT=60000\n\nNODEJS_HELPERS=0\n# 是否写入日志到文件\nLOGFILES=false\n\n# 日志级别\n# LOG_LEVEL=http\n\n# 最大请求体大小(字节)，默认 100MB\n# 受 Vercel Functions 的限制，通过请求体上传时最大不超过 4.5 MB（通过 url 上传则不受限制），详见 https://vercel.com/docs/storage/vercel-blob/server-upload\n# 受 Cloudflare Workers 的限制，通过请求体上传时最大不超过 100 MB（通过 url 上传则不受限制），详见 https://developers.cloudflare.com/workers/platform/limits\n# MAX_BODY_SIZE=104857600\n\n# 图片压缩质量(1-100)，默认 90\n# IMAGE_QUALITY=90\n\n# 授权密钥（Bearer 认证）。可选，如果设置，则所有请求都需要携带此密钥\nAUTH_TOKEN=\n\n# 文件名前缀\n# BUCKET_PREFIX=\n\n# 存储类型，可选值：s3, r2, vercel-blob\n# 如果服务部署在 Cloudflare Workers，并且想要存储到 R2，则可以设置为 'r2'，此时需要修改 wrangler.toml 中的 r2_buckets 相关配置；\n# 如果服务部署在其他平台，想要存储到 R2，请使用 R2 的 S3 兼容接口，参考 https://developers.cloudflare.com/r2/api/s3/api，此时设置为 's3'\n# STORAGE_TYPE=s3\n\n# S3 基础 URL\n# S3_BASE_URL=\n\n# S3 区域\n# S3_REGION=\n\n# S3 存储桶名称\n# S3_BUCKET_NAME=\n\n# S3 访问密钥 ID\n# S3_ACCESS_KEY_ID=\n\n# S3 秘密访问密钥\n# S3_SECRET_ACCESS_KEY=\n\n# S3 端点\n# S3_ENDPOINT=\n\n# Vercel Blob 令牌，参考 https://vercel.com/docs/storage/vercel-blob\n# VERCEL_BLOB_TOKEN=\n\n# R2 基础 URL，仅 Cloudflare Workers 绑定 Cloudflare R2 Storage 可用\n# R2_BASE_URL=\n```\n\n## 🛠️ 开发\n\n```sh\nnpm run dev\n```\n\n## 🔧 编译\n\n```sh\nnpm run build\n```\n\n## 🔍 Lint\n\n```sh\nnpm run lint\n```\n\n## 💾 Commit\n\n```sh\nnpm run commit\n```\n\n## 👤 作者\n\n**CaoMeiYouRen**\n\n-   Website: [https://blog.cmyr.ltd/](https://blog.cmyr.ltd/)\n\n-   GitHub: [@CaoMeiYouRen](https://github.com/CaoMeiYouRen)\n\n## 🤝 贡献\n\n欢迎 贡献、提问或提出新功能！\u003cbr /\u003e如有问题请查看 [issues page](https://github.com/CaoMeiYouRen/sharp-cloud-uploader/issues). \u003cbr/\u003e贡献或提出新功能可以查看[contributing guide](https://github.com/CaoMeiYouRen/sharp-cloud-uploader/blob/master/CONTRIBUTING.md).\n\n## 💰 支持\n\n如果觉得这个项目有用的话请给一颗 ⭐️，非常感谢\n\n\u003ca href=\"https://afdian.com/@CaoMeiYouRen\"\u003e\n  \u003cimg src=\"https://cdn.jsdelivr.net/gh/CaoMeiYouRen/image-hosting-01@master/images/202306192324870.png\" width=\"312px\" height=\"78px\" alt=\"在爱发电支持我\"\u003e\n\u003c/a\u003e\n\n\u003ca href=\"https://patreon.com/CaoMeiYouRen\"\u003e\n    \u003cimg src=\"https://cdn.jsdelivr.net/gh/CaoMeiYouRen/image-hosting-01@master/images/202306142054108.svg\" width=\"312px\" height=\"78px\" alt=\"become a patreon\"/\u003e\n\u003c/a\u003e\n\n## 🌟 Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=CaoMeiYouRen/sharp-cloud-uploader\u0026type=Date)](https://star-history.com/#CaoMeiYouRen/sharp-cloud-uploader\u0026Date)\n\n## 📝 License\n\nCopyright © 2024 [CaoMeiYouRen](https://github.com/CaoMeiYouRen).\u003cbr /\u003e\nThis project is [MIT](https://github.com/CaoMeiYouRen/sharp-cloud-uploader/blob/master/LICENSE) licensed.\n\n---\n\n_This README was generated with ❤️ by [cmyr-template-cli](https://github.com/CaoMeiYouRen/cmyr-template-cli)_\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaomeiyouren%2Fsharp-cloud-uploader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcaomeiyouren%2Fsharp-cloud-uploader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaomeiyouren%2Fsharp-cloud-uploader/lists"}