使用Hono与Cloudflare Workers上传图片至S3遇阻,求代码修改方案
解决Hono + Cloudflare Workers 上传图片到AWS S3的问题
核心问题梳理
你的代码已经引入了@hono-storage/s3的上传中间件,但没有正确利用中间件的自动上传能力,反而保留了未实现的上传逻辑;同时冗余的parseBody调用会和中间件的请求解析逻辑冲突,导致无法正确获取文件信息。
修改后的完整可运行代码
import { Hono } from "hono"; import { S3Client } from "@aws-sdk/client-s3"; import { HonoS3Storage } from "@hono-storage/s3"; // 封装S3客户端创建逻辑 const createS3Client = (accessKeyId: string, secretAccessKey: string) => new S3Client({ region: "ap-southeast-2", credentials: { accessKeyId, secretAccessKey, }, // Cloudflare Workers环境下必须显式指定S3端点,避免请求适配异常 endpoint: "https://s3.ap-southeast-2.amazonaws.com", }); // 配置Hono S3存储实例 const s3Storage = new HonoS3Storage({ // 生成唯一文件名,避免覆盖 key: (_, file) => `${file.originalname}-${Date.now()}.${file.extension}`, bucket: "myblogiumbk1", // 从环境变量获取AWS密钥创建客户端 client: (c) => createS3Client(c.env.AWS_ACCESS_KEY_ID, c.env.AWS_SECRET_ACCESS_KEY), }); // 上传接口路由 userRoute.post('/api/upload', s3Storage.single("file"), async (c) => { try { // 中间件已完成文件解析和上传,直接从请求中获取上传后的文件信息 const uploadedFile = c.req.valid("file"); if (!uploadedFile) { return c.json({ error: "未检测到上传文件" }, 400); } // 返回上传成功的关键信息,方便前端使用 return c.json({ message: "图片上传成功", fileKey: uploadedFile.key, accessUrl: `https://myblogiumbk1.s3.ap-southeast-2.amazonaws.com/${uploadedFile.key}` }); } catch (e) { console.error("上传失败详情:", e); // 返回具体错误信息便于调试 return c.json({ error: e instanceof Error ? e.message : "内部服务器错误" }, 500); } });
关键修改说明
- 完全利用中间件能力:
s3Storage.single("file")中间件会自动完成请求体解析、文件格式校验、S3上传全流程,无需手动编写上传逻辑,上传结果可通过c.req.valid("file")直接获取。 - 修复Cloudflare环境适配:添加S3端点配置,避免Workers环境下的请求协议/地址适配问题。
- 移除冗余代码:删除了和中间件冲突的
c.req.parseBody()调用,避免数据解析异常。 - 优化错误反馈:捕获具体错误信息返回,方便排查问题。
- 增强响应实用性:返回文件的存储Key和直接访问URL,前端可直接使用。
额外配置注意事项
- 确保Cloudflare Workers的环境变量
AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY已正确配置,且对应IAM用户拥有S3桶的PutObject权限。 - 检查S3桶的CORS配置,允许Cloudflare Workers的域名发起跨域请求。
- 如需限制文件类型,可在S3存储配置中添加过滤规则:
const s3Storage = new HonoS3Storage({ // 其他配置... filter: (file) => ["jpg", "jpeg", "png", "gif"].includes(file.extension.toLowerCase()) });
内容的提问来源于stack exchange,提问作者Dhruv Bandi
相关产品推荐
相关产品推荐

