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

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


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


录制声音
准备请求(这一次,将调用needNewBodyStream方法)
准备身体数据
将输入流(从主体数据初始化)传递给完成处理程序


码:

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。失败的步骤是:


录制声音
准备身体数据
获取流对
准备请求(这一次,将调用needNewBodyStream方法)
将输入流传递给完成处理程序
用输出流写入数据


当我检查委托方法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。

关于swift - 无法使用有限的流对执行流式请求,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51281890/

10-08 23:29