HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5
Content-Length: 282
--3d6b6a416f9b5
Content-Type: video/mp4
Content-Range: bytes 0-50/1270
DATA............
--3d6b6a416f9b5
Content-Type: video/mp4
Content-Range: bytes 100-150/1270
eta http-equiv="Content-type" content="text/html; c
--3d6b6a416f9b5--
这是我从Mozilla获得的示例响应。我正在使用swift并使用URLSession创建一个多部分范围的请求。我得到的响应可以转换为[UInt8]
,也可以转换为String
并使用ascii编码获取边界字符串。但是我想知道如何可靠地提取每个范围请求中的内容,而不管内容类型和内容范围如何。我意识到我可以获得--3d6b6a416f9b5 .... --3d6b6a416f9b5
块,但如何准确删除内容标头。
let ranges : [(Int, Int)] = [...]
var range_request = "bytes="
for r in ranges {
range_request += "\(r.0)-\(r.1), "
}
range_request = String(range_request.dropLast(2))
var streamRequest = URLRequest(url: streamURL)
streamRequest.setValue(range_request, forHTTPHeaderField: "Range")
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 1
let session = URLSession(configuration: sessionConfig)
let task = session.downloadTask(with: streamRequest) { (tempLocalURL, response, url_error) in
if url_error != nil {
//handle error
} else {
do {
//assume successful 206 response for now...
let httpResponse = response as! HTTPURLResponse
let data = try Data(contentsOf: tempLocalURL!)
let boundaryPhrase = (httpResponse.allHeaderFields["Content-Type"]! as! String).replacingOccurrences(of: "multipart/byteranges; boundary=", with: "")
let totalData = [UInt8](data)
let stringTotalData = (String(data: data, encoding: .ascii)!
} catch {
//handle error
}
}
}
task.resume()
答案 0 :(得分:0)
let data = try Data(contentsOf: tempLocalURL!)
let content_type = httpResponse.allHeaderFields["Content-Type"]! as! String
let boundary_word = content_type.replacingOccurrences(of: "multipart/byteranges; boundary=", with: "")
let boundary_phrase = "--\(boundary_word)"
let input_data = [UInt8](data)
var bodies : [[UInt8]] = []
var current_body = 0
if boundary_word != "video/mp4" {
let boundary_phrase_ints = [UInt8](boundary_phrase.utf8)
let header_end_ints = [UInt8]("\r\n\r\n".utf8)
var i = 0
var potential_body : [UInt8] = []
while i < (input_data.count - boundary_phrase_ints.count) {
if potential_body == boundary_phrase_ints {
let potential_end_header = Array(input_data[i..<(i + header_end_ints.count)])
if potential_end_header == header_end_ints {
let start = i + header_end_ints.count
let upper_limit = start + ranges[current_body].1 - ranges[current_body].0
bodies.append(Array(input_data[start...upper_limit]))
current_body += 1
i = upper_limit
}
} else {
potential_body = Array(input_data[i..<(i + boundary_phrase_ints.count)])
if potential_body == boundary_phrase_ints {
i += boundary_phrase_ints.count
}
}
i += 1
}
//in my case I don't need to split the data into separate ranges.
} else {
//handle single range case
}
所以我能够解决问题。这是我的代码。在我的情况下,我需要将数据作为[UInt8]处理,就像我要的视频一样,这就是为什么我必须将边界短语转换为[UInt8]以及标头末尾的原因。
因此,通过使用边界短语,您可以提取每个主体-如果您使用字符串进行了提取,则可以只制作组件并删除第一个和最后一个元素,因为它们是虚假的。接下来,在每个正文中,您可以通过查找似乎唯一的“ \ r \ n \ r \ n”来找到标题的末尾。