Summary of Swift uploading files, getting video size, getting video size, and getting image size



Preface

I have encountered some problems while maintaining the Swift project in the past two days. Let me summarize!


1. About video

1. Get the size of the video and pass in the video file URL.

 static func getVideoSize(by url: URL?) -> CGSize {
    
    
        var size: CGSize = .zero
        guard let url = url else {
    
    
            return size
        }
        let asset = AVAsset(url: url)
        let tracks = asset.tracks(withMediaType: AVMediaType.video)
        guard let track = tracks.first else {
    
    
            return size
        }

        let t = track.preferredTransform
        size = CGSize(width: track.naturalSize.height, height: track.naturalSize.width)

        if t.a == 0 && t.b == 1.0 && t.c == -1.0 && t.d == 0 {
    
    
            size = CGSize(width: track.naturalSize.height, height: track.naturalSize.width)
        } else if t.a == 0 && t.b == -1.0 && t.c == 1.0 && t.d == 0 {
    
    
            // PortraitUpsideDown
            size = CGSize(width: track.naturalSize.height, height: track.naturalSize.width)
        } else if t.a == 1.0 && t.b == 0 && t.c == 0 && t.d == 1.0 {
    
    
            // LandscapeRight
            size = CGSize(width: track.naturalSize.width, height: track.naturalSize.height)
        }else if t.a == -1.0 && t.b == 0 && t.c == 0 && t.d == -1.0 {
    
    
            // LandscapeLeft
            size = CGSize(width: track.naturalSize.width, height: track.naturalSize.height)
        }
        return size
    }

2. Get video file size

func wm_getFileSize(_ url:URL) -> Double {
    
    
        if let fileData:Data = try? Data.init(contentsOf: url) {
    
    
            let size = Double(fileData.count) / (1024.00 * 1024.00)
            return size
        }
        return 0.00
    }

3. To get the duration of the video, you can actually use asset.duration directly. Asset is a PHAsset type.

        let asset11 = AVURLAsset(url: videoURL) as AVURLAsset
        let totalSeconds = Int(CMTimeGetSeconds(asset11.duration))
        let minutes = totalSeconds / 60
        let seconds = totalSeconds % 60
        let mediaTime = String(format:"%02i:%02i",minutes, seconds)
        print("打印视频的时长=======",totalSeconds)

4. Get the video URL

let videoFileName = "\(asset.localIdentifier).mp4".replace("-", new: "").replace("/", new: "")
let videoURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(videoFileName)

5. Get the first frame of the video

    static func splitVideoFileUrlFps(splitFileUrl: URL, fps: Float, splitCompleteClosure: @escaping (Bool, [UIImage]) -> Void) {
    
    

        var splitImages = [UIImage]()
        let optDict = NSDictionary(object: NSNumber(value: false), forKey: AVURLAssetPreferPreciseDurationAndTimingKey as NSCopying)
        let urlAsset = AVURLAsset(url: splitFileUrl, options: optDict as? [String: Any])

        let cmTime = urlAsset.duration
        let durationSeconds: Float64 = CMTimeGetSeconds(cmTime) //视频总秒数

        var times = [NSValue]()
        let totalFrames: Float64 = durationSeconds * Float64(fps) //获取视频的总帧数
        var timeFrame: CMTime

        for i in 0...Int(totalFrames) {
    
    
            timeFrame = CMTimeMake(value: Int64(i), timescale: Int32(fps)) //第i帧, 帧率
            let timeValue = NSValue(time: timeFrame)

            times.append(timeValue)
        }

        let imgGenerator = AVAssetImageGenerator(asset: urlAsset)
        imgGenerator.requestedTimeToleranceBefore = CMTime.zero //防止时间出现偏差
        imgGenerator.requestedTimeToleranceAfter = CMTime.zero
        imgGenerator.appliesPreferredTrackTransform = true //不知道是什么属性,不写true视频帧图方向不对

        let timesCount = times.count

        //获取每一帧的图片
        imgGenerator.generateCGImagesAsynchronously(forTimes: times) {
    
     (requestedTime, image, actualTime, result, error) in

            //times有多少次body就循环多少次。。。

            var isSuccess = false
            switch (result) {
    
    
            case AVAssetImageGenerator.Result.cancelled:
                print("cancelled------")

            case AVAssetImageGenerator.Result.failed:
                print("failed++++++")

            case AVAssetImageGenerator.Result.succeeded:
                let framImg = UIImage(cgImage: image!)
                splitImages.append(framImg)

                if (Int(requestedTime.value) == (timesCount - 1)) {
    
     //最后一帧时 回调赋值
                    isSuccess = true
                    splitCompleteClosure(isSuccess, splitImages)
                    print("completed")
                }
            }
        }
    }

2. About pictures

1. Get the image size

static func getImageSize(asset:PHAsset) -> Float{
    
    
        let resource = PHAssetResource.assetResources(for: asset).first
        if let size = resource?.value(forKey: "fileSize") as? Float {
    
    
            return size/(1024*1024)
        }
        return 0.0
    }

2. Determine the horizontal and vertical screens of online images

    static func isLandscapeImage(_ imageUrl: String?) -> Bool {
    
    
        guard let imageUrl = imageUrl else {
    
    
            return true
        }
        let urlQuery = imageUrl.components(separatedBy: ",")
        //获取长宽值
        guard urlQuery.count > 2,
              let widthStr = urlQuery.first(where: {
    
    $0.hasPrefix("w_")}),
              let heightStr = urlQuery.first(where: {
    
    $0.hasPrefix("h_")}) else {
    
    
            return true
        }

        //从字符串中获取Int类型的长宽
        let nonDigits = CharacterSet.decimalDigits.inverted
        guard let width = Int(widthStr.trimmingCharacters(in: nonDigits)),
              let height = Int(heightStr.trimmingCharacters(in: nonDigits)) else {
    
    
            return true
        }

        if width > height {
    
    
            return true
        }
        return false
    }

3. Use the center of the picture as the center and the smallest side as the side length to crop the square picture.

    static func cropSquareImage(image: UIImage?) -> UIImage? {
    
    
        //将UIImage转换成CGImageRef
        guard  let image = image,
               let sourceImageRef = image.cgImage else {
    
    
            return nil
        }

        let imageWidth = image.size.width * image.scale
        let imageHeight = image.size.height * image.scale
        let width = imageWidth > imageHeight ? imageHeight : imageWidth
        let offsetX = (imageWidth - width) / 2
        let offsetY = (imageHeight - width) / 2

        let rect = CGRect(x: offsetX, y: offsetY, width: width, height: width)
        var newImage: UIImage? = nil
        if let aRef = sourceImageRef.cropping(to: rect) {
    
    
            //按照给定的矩形区域进行剪裁
            newImage = UIImage(cgImage: aRef)
        }

        return newImage
    }

3. About image uploading

1. Use Alamofire to put and upload files

        let sUrl = URL.init(string: putUrl)

        if sUrl == nil {
    
     return }

        let encoder = JSONEncoder()
        let jsonData = try! encoder.encode(data)

        let data1 = "last_value=no".data(using: String.Encoding(rawValue: NSUTF8StringEncoding))

        var request = URLRequest(url: sUrl!)
        request.httpMethod = "PUT"
        request.setValue("image/*", forHTTPHeaderField: "Content-Type")
        request.timeoutInterval = 1000
        request.httpBody = data
        print("data=====",jsonData,"httpBody====",request.httpBody,"httpMethod====",request.httpMethod,"allHTTPHeaderFields====",request.allHTTPHeaderFields,"request====",request)

            Alamofire.request(request).responseJSON {
    
     response in

                print("打印上传====",response)
                switch response.result {
    
    
                case .success(let value):
                    print ("finish")
                    let swiftyJson = JSON(value)
                    print("打印上传====",swiftyJson)
//                    completionHandler(swiftyJson, nil)
                case .failure(let error):
                    print("打印上传错误====",error)
//                    completionHandler(nil, error)
                }
            }

2. Data analysis of Alamofire’s basic upload and return results

/**
 TODO: 二进制流的形式上传
 @data : 上传文件的数据对象
 @URLConvertible : 上传的地址
 
 注意: data的类型是Data,不能直接使用 NSData类型的对象。否则会出现 “Cannot invoke 'upload' with an argument list of type '(NSData?, to: String)'”错误提示。
 */
let dataPath = Bundle.main.path(forResource: "upDataName", ofType: "upDataSuffix")
let upData = NSData.init(contentsOfFile: dataPath!)
let upLoadRequest:UploadRequest = Alamofire.upload(Data.init(referencing: upData!), to: "https://network.net/upload")
// 上面的请求返回一个 “UploadRequest” 对象。我们可以对其进行解析,Alamofire请求数据解析的方法都使用与它。
upLoadRequest.validate().response {
    
     (DDataRequest) in
    if let acceptData = DDataRequest.data {
    
    
        print(String.init(data: acceptData, encoding: String.Encoding.utf8)!)
    }
    if DDataRequest.error != nil {
    
    
        print("上传失败!!!")
    }
}

upLoadRequest.validate().responseJSON {
    
     (DataResponse) in
    if DataResponse.result.isSuccess {
    
    
        print(String.init(data: DataResponse.data!, encoding: String.Encoding.utf8)!)
    }
    if DataResponse.result.isFailure {
    
    
        print("上传失败!!!")
    }
}

upLoadRequest.validate().responseString {
    
     (DataResponse) in
    if DataResponse.result.isSuccess {
    
    
        print(String.init(data: DataResponse.data!, encoding: String.Encoding.utf8)!)
    }
    if DataResponse.result.isFailure {
    
    
        print("上传失败!!!")
    }
}

upLoadRequest.validate().responsePropertyList {
    
     (DataResponse) in
    if DataResponse.result.isSuccess {
    
    
        print(String.init(data: DataResponse.data!, encoding: String.Encoding.utf8)!)
    }
    if DataResponse.result.isFailure {
    
    
        print("上传失败!!!")
    }
}

upLoadRequest.validate().response(queue: DispatchQueue.main) {
    
     (DDataRequest) in
    if let acceptData = DDataRequest.data {
    
    
        print(String.init(data: acceptData, encoding: String.Encoding.utf8)!)
    }
    if DDataRequest.error != nil {
    
    
        print("上传失败!!!")
    }
}

3. Alamofire file upload with progress

/**
 TODO: 二进制流的形式上传
 @data : 上传文件的数据对象
 @URLConvertible : 上传的地址
 
 注意: data的类型是Data,不能直接使用 NSData类型的对象。否则会出现 “Cannot invoke 'upload' with an argument list of type '(NSData?, to: String)'”错误提示。
 */
let dataPath = Bundle.main.path(forResource: "upDataName", ofType: "upDataSuffix")
let upData = NSData.init(contentsOfFile: dataPath!)
let upLoadRequest:UploadRequest = Alamofire.upload(Data.init(referencing: upData!), to: "https://network.net/upload")
/**
 可获取上传进度
 */
upLoadRequest.uploadProgress {
    
     (progress) in
     // 上传进度
     print(progress.fractionCompleted)
}

upLoadRequest.uploadProgress(queue: DispatchQueue.main) {
    
     (progress) in
    // 上传进度
    print(progress.fractionCompleted)
}

4. Alamofire Data type upload

/**
Data 数据流
File 文件路径
stream 输入流
multipartFormData 多文件上传

 TODO: 二进制流的形式上传
 @data : 上传文件的数据对象
 @URLConvertible : 上传的地址
 
 注意: data的类型是Data,不能直接使用 NSData类型的对象。否则会出现 “Cannot invoke 'upload' with an argument list of type '(NSData?, to: String)'”错误提示。
 */
let dataPath = Bundle.main.path(forResource: "upDataName", ofType: "upDataSuffix")
let upData = NSData.init(contentsOfFile: dataPath!)
let upLoadRequest:UploadRequest = Alamofire.upload(Data.init(referencing: upData!), to: "https://network.net/upload")
// 上面的请求返回一个 “UploadRequest” 对象。我们可以对其进行解析,Alamofire请求数据解析的方法都使用与它。
upLoadRequest.validate().response {
    
     (DDataRequest) in
    if let acceptData = DDataRequest.data {
    
    
        print(String.init(data: acceptData, encoding: String.Encoding.utf8)!)
    }
    if DDataRequest.error != nil {
    
    
        print("上传失败!!!")
    }
}

5. Alamofire File type upload

/**
 TODO: 通过文件路径上传
 
 @fileURL : 上传文件的路径
 @URLConvertible : 上传文件的网址
 
 注意: fileURL 要转化一下,否则会报 “Cannot invoke 'upload' with an argument list of type '(String, to: String)'”错。
 */
Alamofire.upload(URL.init(fileURLWithPath: dataPath!), to: "https://network.net/upload").validate().responseData {
    
     (DDataRequest) in
    if DDataRequest.result.isSuccess {
    
    
        print(String.init(data: DDataRequest.data!, encoding: String.Encoding.utf8)!)
    }
    if DDataRequest.result.isFailure {
    
    
        print("上传失败!!!")
    }
}

6. Alamofire’s multipartFormData form upload

/**
 TODO: 多部分数据上传
 */
Alamofire.upload(multipartFormData: {
    
     (MFData) in
    MFData.append(upData! as Data, withName: "NetWork")
    MFData.append(upData! as Data, withName: "NetWork小贱")
}, to: "https://network.net/upload") {
    
     (SMResult) in
    switch SMResult {
    
    
    case .success(let request, let streamingFromDisk, let streamFileURL):
        print(streamFileURL!,request,streamingFromDisk)
        request.responseJSON(completionHandler: {
    
     (DResponse) in
            if DResponse.result.isSuccess {
    
    
                print("上传成功!!!")
            }
        })
        break
    case .failure(_):
        print("上传失败!!!")
        break
    }
}

7. Data type request upload

/**
 TODO: 可以自定义请求的二进制流上传
 */
let uploadRequest = URLRequest.init(url: URL.init(fileURLWithPath: dataPath!), cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20)
Alamofire.upload(upData! as Data , with:uploadRequest).validate().responseJSON {
    
     (dataResponse) in
    if dataResponse.result.isSuccess {
    
    
        let acceptData = dataResponse.data
        print(String.init(data: acceptData!, encoding: String.Encoding.utf8)!)
    }
    if dataResponse.result.isFailure {
    
    
        print("上传失败!!!")
    }
}

8. File type request upload

/**
 TODO: 可以自定义请求的数据路径形式上传
 */
Alamofire.upload(URL.init(fileURLWithPath: dataPath!), with: uploadRequest).validate().response(queue: DispatchQueue.main) {
    
     (DDResponse) in
    if let acceptData = DDResponse.data {
    
    
        print(String.init(data: acceptData, encoding: String.Encoding.utf8)!)
    }
    if DDResponse.error != nil {
    
    
        print("上传失败!!!")
    }
}

9. Stream type upload

/**
 TODO: 可以自定义请求的数据输入流形式上传
 */
Alamofire.upload(inPutStraeam, with: uploadRequest).validate().responseJSON {
    
     (DataResponse) in
    if DataResponse.result.isSuccess {
    
    
        print("上传成功")
    }
    if DataResponse.result.isFailure {
    
    
        print("上传失败!!!")
    }
}

10. MultipartFormData type upload

/**
 TODO: 可定义请去形式的多部分上传
 */
Alamofire.upload(multipartFormData: {
    
     (MFData) in
    MFData.append(upData! as Data, withName: "NetWork")
    MFData.append(upData! as Data, withName: "NetWork小贱")
}, with: uploadRequest) {
    
     (SMResult) in
    switch SMResult {
    
    
    case .success(let request, let streamingFromDisk, let streamFileURL):
        print(streamFileURL!,request,streamingFromDisk)
        request.responseJSON(completionHandler: {
    
     (DResponse) in
            if DResponse.result.isSuccess {
    
    
                print("上传成功!!!")
            }
        })
        break
    case .failure(_):
        print("上传失败!!!")
        break
    }
}

11、

Summarize

This is a summary of some of the problems and methods I encountered in the past two days. I hope it can help you!

Guess you like

Origin blog.csdn.net/smileKH/article/details/130623677