【问题标题】:Use FormData in an HTTP Response in Deno/Oak在 Deno/Oak 的 HTTP 响应中使用 FormData
【发布时间】:2021-09-10 20:28:47
【问题描述】:

我知道我可以在客户端创建一个 FormData 并将其发送到服务器(在本例中我使用的是 Deno/Oak),然后从那里读取它。

但是反之亦然吗?

如果我在 Oak 中有一条路由,并且我希望它发送多部分响应(带有一个或多个 blob,以及一个或多个字符串),我该怎么做?

【问题讨论】:

    标签: response multipart form-data deno oak


    【解决方案1】:

    Oak 的automatic response body handling 支持FormData,因此您可以将context.response.body 设置为FormData 的实例,然后Oak 会处理其余的事情。例如:

    import { Application } from "https://deno.land/x/oak@v9.0.0/mod.ts";
    
    const app = new Application();
    
    app.use((ctx) => {
      const data = new FormData();
      data.append("string1", "Hi");
      data.append("string2", "Bye");
      data.append("blob1", new Blob(['<a id="a">Hi</a>'], { type: "text/xml" }));
      data.append("blob2", new Blob(['<b id="b">Bye</b>'], { type: "text/xml" }));
      ctx.response.body = data;
    });
    
    await app.listen({ port: 8000 });
    
    % curl localhost:8000
    ------7115155097707325061106360125
    Content-Disposition: form-data; name="string1"
    
    Hi
    ------7115155097707325061106360125
    Content-Disposition: form-data; name="string2"
    
    Bye
    ------7115155097707325061106360125
    Content-Disposition: form-data; name="blob1"; filename="blob"
    Content-Type: text/xml
    
    <a id="a">Hi</a>
    ------7115155097707325061106360125
    Content-Disposition: form-data; name="blob2"; filename="blob"
    Content-Type: text/xml
    
    <b id="b">Bye</b>
    ------7115155097707325061106360125--
    

    同样可以直接在 Deno 中完成,无需任何额外的框架:

    const server = Deno.listen({ port: 8000 });
    
    for await (const conn of server) serveHttp(conn);
    
    async function serveHttp(conn: Deno.Conn) {
      const httpConn = Deno.serveHttp(conn);
      for await (const requestEvent of httpConn) {
        const data = new FormData();
        data.append("string1", "Hi");
        data.append("string2", "Bye");
        data.append("blob1", new Blob(['<a id="a">Hi</a>'], { type: "text/xml" }));
        data.append("blob2", new Blob(['<b id="b">Bye</b>'], { type: "text/xml" }));
        requestEvent.respondWith(new Response(data));
      }
    }
    

    【讨论】:

    • 非常感谢您的帮助,mfulton26。它适用于 curl,甚至适用于视频中的 blob。不幸的是,它不适用于浏览器客户端。使用 Insomnia,它返回“无法解析多部分响应:内容类型缺失边界”。我尝试过使用 GET/POST,将 context.response.headers.set("Content-Type", "multipart/form-data") 设置在正文的 Oak 响应之前,并在客户端获取中添加/删除 headers: {"Content-Type": "multipart/form-data"},但没有运气。
    • 有趣的是,它通过 curl 和 Chromium 浏览器对我来说很好,但在 Insomnia 中却不行……有趣的是,我之前在我的答案中添加的本机 Deno 解决方案在 Insomnia 中有效。响应标头也不同; Deno.requestEvent'` resondWith 导致 Content-Type 在其中包含一个“边界”(例如 multipart/form-data; boundary=----7830127428108890346214010889),而 Oak 解决方案没有。这可能是 Oak 中的一个错误。我不肯定。我自己没怎么用过Oak。它只发送`multipart/form-data`...
    • 好的,经过多一点调查,看起来 Insomnia 确实收到了很好的响应。但是,它的“视觉预览”无法解析响应。如果您切换到查看响应“源代码”或“原始数据”,您将按预期看到所有数据。我创建了 2 个 GitHub 问题。如果得到修复或提供一些解决方法等,那么“视觉预览”也应该适合您:1.github.com/oakserver/oak/issues/400 2.github.com/Kong/insomnia/issues/4021我建议订阅这些问题以获取更新。
    • 非常感谢,@mfulton26。正如你所说,我已经尝试过失眠症,是的,它有效。在客户端,使用 fetch api,我收到这样的响应:.then(response =&gt; response.formData()),但它说:“无法将内容解析为 FormData。”,可能是因为缺少边界。无论如何,我已经订阅了 Oak 中的问题,我会坚持下去。
    猜你喜欢
    • 2020-09-29
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-30
    • 2021-04-06
    • 1970-01-01
    相关资源
    最近更新 更多