无法使用有界流对进行流式请求

Unable to do streamed request with bounded stream pair

我正在尝试通过使用流对来使流式请求工作。出于测试目的,我预先录制了一个声音并使用流对并使用输出流写入内容并将输入流传递给此方法的完成处理程序

func urlSession(_ session: URLSession, task: URLSessionTask, needNewBodyStream completionHandler: @escaping (InputStream?) -> Void)

请求成功,没有流对。只需先准备数据并用它初始化一个输入流,然后将其传递给上述方法的完成处理程序。以下是对我有用的步骤

  1. 录制声音
  2. 准备请求(此时会调用needNewBodyStream方法)
  3. 准备正文数据
  4. 将输入流(从正文数据初始化)传递给完成处理程序

代码:

func urlSession(_ session: URLSession, task: URLSessionTask, needNewBodyStream completionHandler: @escaping (InputStream?) -> Void)
{
    NSLog("need new body stream")

    var bodyData = Data()
    bodyData.append(getBoundaryBeginData())

    bodyData.append(getJsonMessageHeaderData())
    bodyData.append(AVSRecognizeRequest().jsonData())
    bodyData.append("\r\n".data(using: String.Encoding.utf8)!)

    bodyData.append(getBoundaryBeginData())
    bodyData.append("Content-Disposition: form-data; name=\"audio\"\r\n".data(using: String.Encoding.utf8)!)
    bodyData.append("Content-Type: application/octet-stream\r\n\r\n".data(using: String.Encoding.utf8)!)

    try! bodyData.append(AudioManager.shared.getRecording()!)

    bodyData.append("\r\n".data(using: String.Encoding.utf8)!)
    bodyData.append(getBoundaryEndData())

    NSLog("Total data length is \(bodyData.count)")

    completionHandler(InputStream.init(data: bodyData))
}

但是,如果我将输入流(来自流对)传递给完成处理程序,然后在之后写入内容,请求将失败并出现 400 错误。该 ff。是失败的步骤:

  1. 录制声音
  2. 准备正文数据
  3. 获取流对
  4. 准备请求(此时会调用needNewBodyStream方法)
  5. 将输入流传递给完成处理程序
  6. 用输出流写入数据

当我检查委托方法时 func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) 发送的总字节数仅为 8192。但我的总数据长度约为 80k。

代码:

public func stopRecognizing()
{
    //*** 1. RECORD A SOUND  

    AudioManager.shared.stopRecording()

    //*** 2. PREPARE BODY DATA

    var bodyData = Data()
    bodyData.append(getBoundaryBeginData())

    bodyData.append(getJsonMessageHeaderData())
    bodyData.append(AVSRecognizeRequest().jsonData())
    bodyData.append("\r\n".data(using: String.Encoding.utf8)!)

    bodyData.append(getBoundaryBeginData())
    bodyData.append("Content-Disposition: form-data; name=\"audio\"\r\n".data(using: String.Encoding.utf8)!)
    bodyData.append("Content-Type: application/octet-stream\r\n\r\n".data(using: String.Encoding.utf8)!)

    try! bodyData.append(AudioManager.shared.getRecording()!)

    bodyData.append("\r\n".data(using: String.Encoding.utf8)!)
    bodyData.append(getBoundaryEndData())

    //*** 3. GET STREAM PAIR

    Stream.getBoundStreams(withBufferSize: bodyData.count, inputStream: &inputStream, outputStream: &outputStream)

    //*** 4. PREPARES THE REQUEST (AFTER THIS IS CALLED, the needNewBodyStream delegate method will be called)
    sendRecognizeRequest()

    //*** 6. WRITE THE DATA WITH OUTPUT STREAM

    outputStream?.open()

    bodyData.withUnsafeBytes(
    {(bytes: UnsafePointer<UInt8>) -> Void in

        outputStream?.write(bytes, maxLength: bodyData.count)

    })
}


func urlSession(_ session: URLSession, task: URLSessionTask, needNewBodyStream completionHandler: @escaping (InputStream?) -> Void)
{
    NSLog("need new body stream")

    //*** 5. PASS IN THE INPUT STREAM

    completionHandler(inputStream)
}

我通过 运行 一个连续读取输入流的线程和一个连续写入数据的输出流测试了自己的流对。我可以清楚地知道写入其他流的数据可以从输入流中读取,因为它们已经绑定。

那么,为什么我的流请求不起作用?

我发现了问题。写完后我必须关闭输出流。当我关闭输出流时,此回调发送的总字节数现在给我的是总数据数 func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) 而不是 8192.