import UIKit
import Foundation
class VNetSpeedTester: NSObject {
typealias UploadSpeedCompletion = (String?) -> Void
typealias DownloadSpeedCompletion = (String?) -> Void
class func testUploadSpeed(completion: @escaping UploadSpeedCompletion) {
let urlString = "https://mensura.cdn-apple.com/api/v1/gm/slurp"
guardleturl =URL(string: urlString)else{
print("Invalid URL")
completion(nil)
return
}
var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 10)
urlRequest.httpMethod="POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
let emptyData = createEmptyData(of: 1048576) // Adjust the size as needed
letjson: [String:Any] = ["file": emptyData.base64EncodedString()]
ifletjsonData =try?JSONSerialization.data(withJSONObject: json,options: []) {
urlRequest.httpBody= jsonData
}else{
print("Failed to encode JSON data")
completion(nil)
return
}
letsessionConfiguration =URLSessionConfiguration.ephemeral
letsession =URLSession(configuration: sessionConfiguration,delegate:nil,delegateQueue:nil)
let startTime = CFAbsoluteTimeGetCurrent()
session.dataTask(with: urlRequest) { (data, response, error)in
ifleterror = error {
print("Error: \(error)")
completion(nil)
return
}
ifletresponse = responseas?HTTPURLResponse{
ifresponse.statusCode==200{
letelapsedTime =CFAbsoluteTimeGetCurrent() - startTime
letuploadSpeed =Double(emptyData.count) / elapsedTime// bytes per second
letspeedString =self.convertBytesToReadableSpeed(bytesPerSecond: uploadSpeed)
print("Upload completed in \(elapsedTime) seconds")
print("Upload speed: \(speedString)")
completion(speedString)
}else{
print("Server returned non-200 status code")
completion(nil)
}
}
}.resume()
}
class func testDownloadSpeed(completion: @escaping DownloadSpeedCompletion) {
guard let url = URL(string: "https://images.apple.com/v/imac-with-retina/a/images/overview/5k_image.jpg") else {
print("Invalid URL")
completion(nil)
return
}
letsession =URLSession(configuration: .default)
let startTime = CFAbsoluteTimeGetCurrent()
lettask = session.downloadTask(with: url) { [self] (location, response, error)in
ifleterror = error {
print("Download error: \(error.localizedDescription)")
completion(nil)
return
}
guardletlocation = locationelse{
print("Download location not found")
completion(nil)
return
}
do{
letfileManager =FileManager.default
letdocumentsURL =tryfileManager.url(for: .documentDirectory,in: .userDomainMask,appropriateFor:nil,create:false)
letdestinationURL = documentsURL.appendingPathComponent(url.lastPathComponent)
try? fileManager.removeItem(at: destinationURL)
tryfileManager.moveItem(at: location,to: destinationURL)
letendTime =CFAbsoluteTimeGetCurrent()
letelapsedTime = endTime - startTime
letfileSize =tryfileManager.attributesOfItem(atPath: destinationURL.path)[.size]as?Int??0
letspeed = fileSize /Int(elapsedTime)
print("Downloaded\(url.lastPathComponent)(\(fileSize)bytes) in\(elapsedTime)seconds. Average speed:\(speed)bytes/sec")
letconvertedSpeed =convertBytesToReadableSpeed(bytesPerSecond:Double(speed))
completion(convertedSpeed)
}catch{
print("Error saving file: \(error.localizedDescription)")
completion(nil)
}
}
task.resume()
}
privateclassfunccreateEmptyData(ofsize:Int) ->Data{
returnData(count: size)
}
private class func convertBytesToReadableSpeed(bytesPerSecond: Double) -> String {
letformatter =ByteCountFormatter()
formatter.allowedUnits = [.useBytes, .useKB, .useMB, .useGB, .useTB]
formatter.countStyle= .file
letspeedString = formatter.string(fromByteCount:Int64(bytesPerSecond))
return"\(speedString)/s"
}
}