在Deno/Oak中如何在HTTP响应里返回FormData格式的multipart内容
Deno/Oak服务端返回multipart响应的实现方案
首先可以明确:你说的反向操作是完全可行的,multipart格式的响应没有传输方向限制,服务端完全可以构造包含字符串、Blob二进制内容的multipart响应返回给客户端。
Oak框架原生支持直接传入FormData实例作为响应体,不需要手动拼接multipart格式的报文,框架会自动处理boundary生成、响应头填充等底层逻辑。
完整服务端实现代码
import { Application, Router } from "https://deno.land/x/oak/mod.ts"; const app = new Application(); const router = new Router(); router.get("/get-multipart-content", async (ctx) => { // 1. 初始化FormData实例 const resForm = new FormData(); // 2. 添加字符串类型字段 resForm.append("fileType", "测试资源包"); resForm.append("uploadTime", new Date().toISOString()); resForm.append("extraInfo", "自定义文本描述内容"); // 3. 添加Blob二进制类型字段,支持多文件 // 示例1:读取本地图片转为Blob添加 const imageBuffer = await Deno.readFile("./test_avatar.png"); resForm.append( "avatar", new Blob([imageBuffer], { type: "image/png" }), "user_avatar.png" // 第三个参数为客户端读取时的默认文件名 ); // 示例2:直接生成文本文件Blob const txtBlob = new Blob(["这是文本文件的内置内容"], { type: "text/plain" }); resForm.append("infoFile", txtBlob, "readme.txt"); // 4. 直接将FormData赋值给响应体即可 ctx.response.body = resForm; // 不需要手动设置Content-Type,Oak会自动生成带正确boundary的multipart/form-data响应头 }); app.use(router.routes()); app.use(router.allowedMethods()); console.log("服务启动于端口8000"); await app.listen({ port: 8000 });
客户端读取响应的示例
前端收到响应后可以直接调用原生response.formData()方法解析内容:
async function getMultipartRes() { const response = await fetch("http://localhost:8000/get-multipart-content"); const formData = await response.formData(); // 读取字符串字段 console.log(formData.get("fileType")); // 输出:测试资源包 // 读取Blob字段 const avatarBlob = formData.get("avatar"); // 可生成临时URL用于资源预览、下载 const avatarUrl = URL.createObjectURL(avatarBlob); }
注意事项
- 给FormData添加Blob字段时如果需要指定客户端可识别的文件名,必须传入第三个参数作为文件名,否则客户端读取的文件名为空
- Oak版本需要≥v10.0,旧版本对FormData作为响应体的支持存在缺陷
- 如果需要使用multipart/mixed等其他multipart子类型,需要手动生成boundary并设置
Content-Type响应头,常规场景下直接用默认的multipart/form-data即可,交由框架自动处理更稳妥
内容的提问来源于stack exchange,提问作者Imagitori
相关产品推荐
相关产品推荐

