多部分HTTP响应

目标是让Node.js / hapi API服务器响应浏览器的AJAX请求,其中包含两件事:

  • 媒体文件(例如图像)
  • 包含有关该文件的元数据的JSON对象

这是两个单独的项目,因为二进制数据不能轻易存储在JSON中。 否则,这将是一个单一的资源。 尽pipe如此,最好是单方面回复。

我们用multipart/form-data在一个请求中上传这些multipart/form-data 。 在这种情况下,浏览器提供了一个内置的机制来序列化主体,大多数服务器端框架知道如何parsing它。 但是,如何在相反的方向上做出同样的回应呢? 也就是说,服务器应该如何序列化主体以将其传输到客户端?

从我所知道的, multipart/mixed可能是一个有用的内容types。 但是很less有人谈论这个。 大多数人似乎都提供了两个单独的GET路线,每个路线一个。 我不喜欢这样做,因为这会让你受到比赛条件的影响。 我错过了什么?

另见我在hapijs的讨论/讨论#563 。

如果你打算采用多部分格式,我认为在上传(POST / PUT)和检索(GET)过程中使用完全相同的格式并不存在任何固有的错误。

我认为在使用HTTP时,在两个方向使用相同的在线格式绝对是一种优雅。

但是,如果你想在PUT / POST和JSON中使用GET发送表单数据,那么我会开始质疑这是否是正确的做法。

如果他们只是想显示图像,multipart会让客户烦恼。 你有没有考虑过使用不同的端点? 一个是图像,另一个是元数据? 你有什么理由把他们合并成一个单一的资源?

或者,您也可以尝试在图像中embedded信息。 例如JPEG允许使用EXIF添加自定义数据。 至less你保留了直接打开图像的能力。

但是,如果你只是想embedded一个图像+一个json对象,我会最后说multipart/mixed是合适的,但要记住:

  1. 消费可能有点不方便
  2. 这也有点不寻常
  3. 我相当确定,多部分编码将要求你用一些7位编码来编码你的图像,这本质上会导致请求大小炸掉很多。

您可以将响应作为multipart/form-data并使用Response.formData()读取客户端的响应

 fetch("/path/to/server", {method:"POST", body:formData}) .then(response => response.formData()) .then(fd => { for (let [key, prop] of fd) { console.log(key, prop) } }) 
 let fd = new FormData(); fd.append("json", JSON.stringify({ file: "image" })); fetch("data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==") .then(response => response.blob()) .then(blob => { fd.append("file", blob); new Response(fd) .formData() .then(formData => { for (let [key, data] of formData) { console.log(key, data) } }) })