Ios 使用URLSession将视频上载到Vimeo
我正在尝试使用他们的RESTAPI将视频上传到Vimeo。 首先,我发表一篇文章,在API上创建视频,然后从摄像机中选择视频,并发送带有一些参数的补丁。 问题是,视频似乎上传成功,我得到的HTML没有任何错误,这似乎是成功的,但在网站上没有显示视频,KB大小只有0 以下是我的补丁方法:Ios 使用URLSession将视频上载到Vimeo,ios,swift,video,upload,vimeo,Ios,Swift,Video,Upload,Vimeo,我正在尝试使用他们的RESTAPI将视频上传到Vimeo。 首先,我发表一篇文章,在API上创建视频,然后从摄像机中选择视频,并发送带有一些参数的补丁。 问题是,视频似乎上传成功,我得到的HTML没有任何错误,这似乎是成功的,但在网站上没有显示视频,KB大小只有0 以下是我的补丁方法: let request = NSMutableURLRequest(url: "https://api.vimeo.com/me/videos") request.httpMethod = "PA
let request = NSMutableURLRequest(url: "https://api.vimeo.com/me/videos")
request.httpMethod = "PATCH"
request.cachePolicy = .reloadIgnoringLocalCacheData
request.httpBody = mediaData // Data()
request.setValue("Upload-Offset", forHTTPHeaderField: "0")
request.setValue("Content-Type", forHTTPHeaderField: "application/offset+octet-stream")
request.setValue("Authorization", forHTTPHeaderField: "Bearer 1233131312")
request.setValue("Tus-Resumable", forHTTPHeaderField: "1.0.0")
let newTask = session.uploadTask(withStreamedRequest: request)
newTask.resume()
已经尝试过:
request.httpBodyStream = InputStream(data: mediaData)
或:
以下是VIMEO的文件:
任何人都能有一个实际有效的例子或片段吗
[更新]:
发出请求的类:
import Foundation
case get
case post
case put
case delete
case patch
var verbName: String {
switch self {
case .get:
return "GET"
case .post:
return "POST"
case .put:
return "PUT"
case .delete:
return "DELETE"
case .patch:
return "PATCH"
}
}
var containsBody: Bool {
return self == .post || self == .put || self == .patch
}
}
final class MediaUploader: URLSessionTaskDelegate, URLSessionDataDelegate {
private let dispatchGroup = DispatchGroup()
private let globalSSLEnabled: Bool = true
var outputStream: OutputStream? = nil
private var buffer:NSMutableData = NSMutableData()
convenience init?(domain: String) {
self.init(domain: domain)
}
func request(verb: HTTPVerb, action: String, parameters: JSONDictionary = [:], headers: [String : String] = [:], sslEnabled: Bool = true, media: MediaData, completion: @escaping (_ response: HTTPResponse) -> Void) {
let sslEnabled = self.globalSSLEnabled || sslEnabled
guard let request = buildRequest(verb: verb, action: action, parameters: parameters, media: media, sslEnabled: sslEnabled) else {
return
}
headers.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) }
let session = buildURLSession(sslEnabled: sslEnabled)
conditionalLog(items: "REQUEST [\(verb.verbName)]")
conditionalLog(items: "URL: \(request.url?.absoluteString ?? "[invalid]")")
conditionalLog(items: "Headers: \(String(describing: request.allHTTPHeaderFields))")
conditionalLog(items: "Parameters: \(parameters)")
createSessionWithDataTask(session: session, request: request as URLRequest, mediaData: media, completion: completion)
}
func buildURLSession(sslEnabled: Bool) -> URLSession {
if !sslEnabled {
return URLSession(configuration: .default)
}
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
return session
}
func createSessionWithDataTask(session: URLSession, request: URLRequest, mediaData: MediaData,completion: @escaping (HTTPResponse) -> Void) {
let queue = DispatchQueue(label: "com.lassie.dispatchgroup", attributes: .concurrent, target: nil)
dispatchGroup.enter()
queue.async(group: dispatchGroup) {
self.dataTaskWorker(session: session, request: request as URLRequest, mediaData: mediaData, completion: completion)
self.dispatchGroup.leave()
}
}
func dataTaskWorker(session: URLSession, request: URLRequest, mediaData: MediaData, completion: @escaping (_ response: HTTPResponse) -> Void) {
guard let data = mediaData.data() else {
return
}
// let newTask = session.uploadTask(withStreamedRequest: request)
// let newTask = session.uploadTask(with: request, from: data)
//session.uploadTask(with: request, from: data)
let task = session.uploadTask(withStreamedRequest: request) { data, response, error in
self.conditionalLog(items: "RESPONSE: \(String(describing: response))")
if let eRROR = error {
self.conditionalLog(items: "ERROR : \(String(describing: eRROR))")
}
self.parseResponse(data: data, response: response, error: error, completion: completion)
session.finishTasksAndInvalidate()
}
newTask.resume()
}
func buildRequest(verb: HTTPVerb, action: String, parameters: JSONDictionary = [:], media: MediaData, sslEnabled: Bool) -> NSMutableURLRequest? {
let suffix = buildAction(verb: verb, action: action, parameters: parameters)
guard let fullUrl = suffix.isEmpty ? baseURL(sslEnabled: sslEnabled) : URL(string: suffix, relativeTo: baseURL(sslEnabled: sslEnabled)), let mediaData = media.data() else {
assert(false, "Invalid url/parameters")
return nil
}
let request = NSMutableURLRequest(url: fullUrl)
request.httpMethod = verb.verbName
request.cachePolicy = .reloadIgnoringLocalCacheData
request.httpBody = mediaData
// request.httpBodyStream = InputStream(data: mediaData)
return request
}
// MARK: URLSessionDataTask
func urlSession(_ session: URLSession, task: URLSessionTask, needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) {
self.closeStream()
var inStream: InputStream? = nil
var outStream: OutputStream? = nil
Stream.getBoundStreams(withBufferSize: 4096, inputStream: &inStream, outputStream: &outStream)
self.outputStream = outStream
completionHandler(inStream)
}
private func closeStream() {
if let stream = self.outputStream {
stream.close()
self.outputStream = nil
}
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
buffer.append(data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
let percentageSent = Double(totalBytesSent) / Double(totalBytesExpectedToSend)
print("PERCENTAGE - \(percentageSent)")
}
private func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
completionHandler(.allow)
}
private func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let e = error {
print("ERROR")
} else {
self.conditionalLog(items: "RESPONSE DATA: \(String(data: buffer as Data, encoding: .utf8))")
}
}
}
您正在使用
session.uploadTask(withStreamedRequest:request)
。后端文件大小为0的原因是您没有关闭流,类似于inputStream.finished=true
。因此,您必须确定何时要关闭该流
无论如何,因为你已经准备好了数据。我想说,您可以使用
uploadTask(with:from:completionHandler:)
,或者甚至可以切换到uploadTask(with:fromFile:completionHandler:)
,但这是一种快速的方式。使用URLRequest
,而不是NS[Mutable]URLRequest
。什么是“补丁”http方法?你不是说“发帖”吗?为什么不试试呢。如果你还想手动检查代码,我可以检查你的代码,@Gihan,我不想在项目上添加其他依赖项,这只是一种上传方法对不起,忘了放置整个代码,但我确实关闭了流,你可以在类中检查这一点,为什么你仍然使用httpBody
而不是httpBodyStream
?
import Foundation
case get
case post
case put
case delete
case patch
var verbName: String {
switch self {
case .get:
return "GET"
case .post:
return "POST"
case .put:
return "PUT"
case .delete:
return "DELETE"
case .patch:
return "PATCH"
}
}
var containsBody: Bool {
return self == .post || self == .put || self == .patch
}
}
final class MediaUploader: URLSessionTaskDelegate, URLSessionDataDelegate {
private let dispatchGroup = DispatchGroup()
private let globalSSLEnabled: Bool = true
var outputStream: OutputStream? = nil
private var buffer:NSMutableData = NSMutableData()
convenience init?(domain: String) {
self.init(domain: domain)
}
func request(verb: HTTPVerb, action: String, parameters: JSONDictionary = [:], headers: [String : String] = [:], sslEnabled: Bool = true, media: MediaData, completion: @escaping (_ response: HTTPResponse) -> Void) {
let sslEnabled = self.globalSSLEnabled || sslEnabled
guard let request = buildRequest(verb: verb, action: action, parameters: parameters, media: media, sslEnabled: sslEnabled) else {
return
}
headers.forEach { request.setValue($0.value, forHTTPHeaderField: $0.key) }
let session = buildURLSession(sslEnabled: sslEnabled)
conditionalLog(items: "REQUEST [\(verb.verbName)]")
conditionalLog(items: "URL: \(request.url?.absoluteString ?? "[invalid]")")
conditionalLog(items: "Headers: \(String(describing: request.allHTTPHeaderFields))")
conditionalLog(items: "Parameters: \(parameters)")
createSessionWithDataTask(session: session, request: request as URLRequest, mediaData: media, completion: completion)
}
func buildURLSession(sslEnabled: Bool) -> URLSession {
if !sslEnabled {
return URLSession(configuration: .default)
}
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
return session
}
func createSessionWithDataTask(session: URLSession, request: URLRequest, mediaData: MediaData,completion: @escaping (HTTPResponse) -> Void) {
let queue = DispatchQueue(label: "com.lassie.dispatchgroup", attributes: .concurrent, target: nil)
dispatchGroup.enter()
queue.async(group: dispatchGroup) {
self.dataTaskWorker(session: session, request: request as URLRequest, mediaData: mediaData, completion: completion)
self.dispatchGroup.leave()
}
}
func dataTaskWorker(session: URLSession, request: URLRequest, mediaData: MediaData, completion: @escaping (_ response: HTTPResponse) -> Void) {
guard let data = mediaData.data() else {
return
}
// let newTask = session.uploadTask(withStreamedRequest: request)
// let newTask = session.uploadTask(with: request, from: data)
//session.uploadTask(with: request, from: data)
let task = session.uploadTask(withStreamedRequest: request) { data, response, error in
self.conditionalLog(items: "RESPONSE: \(String(describing: response))")
if let eRROR = error {
self.conditionalLog(items: "ERROR : \(String(describing: eRROR))")
}
self.parseResponse(data: data, response: response, error: error, completion: completion)
session.finishTasksAndInvalidate()
}
newTask.resume()
}
func buildRequest(verb: HTTPVerb, action: String, parameters: JSONDictionary = [:], media: MediaData, sslEnabled: Bool) -> NSMutableURLRequest? {
let suffix = buildAction(verb: verb, action: action, parameters: parameters)
guard let fullUrl = suffix.isEmpty ? baseURL(sslEnabled: sslEnabled) : URL(string: suffix, relativeTo: baseURL(sslEnabled: sslEnabled)), let mediaData = media.data() else {
assert(false, "Invalid url/parameters")
return nil
}
let request = NSMutableURLRequest(url: fullUrl)
request.httpMethod = verb.verbName
request.cachePolicy = .reloadIgnoringLocalCacheData
request.httpBody = mediaData
// request.httpBodyStream = InputStream(data: mediaData)
return request
}
// MARK: URLSessionDataTask
func urlSession(_ session: URLSession, task: URLSessionTask, needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) {
self.closeStream()
var inStream: InputStream? = nil
var outStream: OutputStream? = nil
Stream.getBoundStreams(withBufferSize: 4096, inputStream: &inStream, outputStream: &outStream)
self.outputStream = outStream
completionHandler(inStream)
}
private func closeStream() {
if let stream = self.outputStream {
stream.close()
self.outputStream = nil
}
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
buffer.append(data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
let percentageSent = Double(totalBytesSent) / Double(totalBytesExpectedToSend)
print("PERCENTAGE - \(percentageSent)")
}
private func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
completionHandler(.allow)
}
private func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let e = error {
print("ERROR")
} else {
self.conditionalLog(items: "RESPONSE DATA: \(String(data: buffer as Data, encoding: .utf8))")
}
}
}