如何使用typescript / javascript正确解析multipart / byteranges响应?

时间:2016-12-27 16:09:01

标签: javascript typescript xmlhttprequest multipart

我是TypeScript / JavaScript的新手,我正在尝试使用TypeScript和XMLHttpRequest 2为二进制文件的不同部分执行多部分范围请求(RFC 7233)。

根据RFC 7233,multipart / byteranges响应具有以下内容:

 HTTP/1.1 206 Partial Content
 Date: Wed, 15 Nov 1995 06:25:24 GMT
 Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
 Content-Length: 1741
 Content-Type: multipart/byteranges; boundary=THIS_STRING_SEPARATES

 --THIS_STRING_SEPARATES
 Content-Type: application/pdf
 Content-Range: bytes 500-999/8000

 ...the first range...
 --THIS_STRING_SEPARATES
 Content-Type: application/pdf
 Content-Range: bytes 7000-7999/8000

 ...the second range
 --THIS_STRING_SEPARATES--

我看到两个选项:

  1. 将响应的主体视为二进制数据数组(设置XMLHttpRequest.responseType = "arraybuffer"),将边界字符串转换为二进制,在二进制数据数组中搜索由边界字符串转换为分隔的每个主体部分二进制,提取每个有效负载的标头并将其转换为字符串?或者,
  2. 与上面类似,但将主体视为字符串(设置XMLHttpRequest.responseType = "text"),识别由边界字符串分隔的正文部分,并将有效负载转换为二进制数据数组?
  3. 在javascript / typescript中处理/解析此类响应的正确方法是什么,因为响应包含多个正文部分,每个部分都有自己的标题(字符串)和有效负载(二进制)?

    有更简单的方法吗?

    欢迎任何建议。谢谢!

1 个答案:

答案 0 :(得分:4)

我甚至不确定您是如何使用"arraybuffer"响应类型进行的,但我之前使用过它来解析多部分/字节范围响应:

function parseMultipartBody (body, boundary) {
  return body.split(`--${boundary}`).reduce((parts, part) => {
    if (part && part !== '--') {
      const [ head, body ] = part.trim().split(/\r\n\r\n/g)
      parts.push({
        body: body,
        headers: head.split(/\r\n/g).reduce((headers, header) => {
          const [ key, value ] = header.split(/:\s+/)
          headers[key.toLowerCase()] = value
          return headers
        }, {})
      })
    }
    return parts
  }, [])
}

为了将它与XMLHttpRequest一起使用,它可能看起来像这样:

const client = new XMLHttpRequest()
client.open('GET', 'example.pdf', true)
client.setRequestHeader('Range', 'bytes=500-999,7000-7999')
client.onreadystatechange = function() {
  if (client.readyState == 4 && client.status === 206) {
    const boundary = client.getResponseHeader('Content-Type').match(/boundary=(.+)$/i)[1]
    if (boundary) console.log('PARTS', parseMultipartBody(client.resposeText, boundary))
  }
}
client.send()

示例响应的输出如下所示:

[
  {
    "body": "...the first range...",
    "headers": {
      "content-type": "application/pdf",
      "content-range": "bytes 500-999/8000"
    }
  },
  {
    "body": "...the second range",
    "headers": {
      "content-type": "application/pdf",
      "content-range": "bytes 7000-7999/8000"
    }
  }
]