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