3

I've created two different functions for uploading PHASSets to my backend -

the uploadImageAsset() uploads all of the assets that are images:

func uploadImageAsset(asset: PHAsset, projectRef: String) {
    let userID = Auth.auth().currentUser?.uid
    let db = Firestore.firestore()
    let dbRef = db.collection("projects").document(projectRef)
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    option.isSynchronous = false
    option.isNetworkAccessAllowed = true
    option.resizeMode = .exact
    option.version = .original
    option.deliveryMode = .highQualityFormat
    let imageSize = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
    let uniqueImageID = NSUUID().uuidString
    let storageRef = Storage.storage().reference().child("project-images").child("\(uniqueImageID).jpeg")

    manager.requestImage(for: asset, targetSize: imageSize, contentMode: .aspectFill, options: option) { (image, info) in
        let uploadData = image?.jpegData(compressionQuality: 0.6)
        storageRef.putData(uploadData!, metadata: nil, completion: {
            (metadata, error) in

            if error != nil {
                return
            } else {
                storageRef.getMetadata(completion: { (metadata, err) in
                    if let error = err {
                        print(error)
                    } else {
                        storageRef.downloadURL(completion: { (url, err) in
                            if let error = err {
                                print(error)
                            } else {
                                self.imageURLs.append((url?.absoluteString)!)
                                dbRef.updateData(["image": self.imageURLs], completion: { (err) in
                                    if err != nil {
                                        print(err)
                                    } else {
                                        SVProgressHUD.dismiss(withDelay: 0.3)
                                        self.dismiss(animated: true, completion: nil)
                                    }
                                })
                            }
                        })
                    }
                })
            }
        })
    }
}

and the uploadProjectVideos() uploads all of the assets that are videos:

func uploadVideoAsset(asset: PHAsset, projectRef: String) {
    let userID = Auth.auth().currentUser?.uid
    let db = Firestore.firestore()
    let dbRef = db.collection("projects").document(projectRef)
    let manager = PHImageManager.default()
    let option = PHVideoRequestOptions()
    option.isNetworkAccessAllowed = true
    option.deliveryMode = PHVideoRequestOptionsDeliveryMode.highQualityFormat

    manager.requestAVAsset(forVideo: asset, options: option) { (video, videoAudio, nil) in
        let avurlAsset = video as! AVURLAsset
        let fileURL = avurlAsset.url.absoluteString as! URL
        let fileName = NSUUID().uuidString + ".mov"
        let uploadTask = Storage.storage().reference().child(fileName).putFile(from: fileURL, metadata: nil, completion: { (metaData, error) in
            if error != nil {
                print("Failed upload of video", error)
                return
            }

            Storage.storage().reference().child(fileName).downloadURL { (url, error) in
                self.imageURLs.append("\(url)")
                dbRef.updateData(["image": self.imageURLs], completion: { (err) in
                    if err != nil {
                        print(err)
                    } else {
                        SVProgressHUD.dismiss(withDelay: 0.3)
                        self.dismiss(animated: true, completion: nil)
                    }
                })
            }
        })
    }
}

When it comes to uploading images, my function for that works perfectly. However, my function for uploading videos is returning nil. Videos aren't being uploaded to the backend at all.

This is my first time working with PHAssets and Im really confused as to how I can get the video url of a phasset and upload it

Vandal
  • 708
  • 1
  • 8
  • 21
  • are you sure avURLAsset.url.absoluteString as! URL works? can you check your fileURL and debug putFile it actually fetches the file from the specified file path – Joshua Aug 20 '19 at 02:20
  • 1
    A PHAsset has no URL. Pure duplicate of many existing questions. See https://stackoverflow.com/search?q=Upload+video+PHAsset – matt Sep 08 '19 at 14:09

1 Answers1

-2

You can use the requestAVAsset(forVideo:options:resultHandler:) method as shown in the documentation: https://developer.apple.com/documentation/photokit/phimagemanager/1616935-requestavasset. And here's a little handy extension originally made by @iMHitesh Surani, updated to swift by @diegomen:

extension PHAsset {

func getURL(completionHandler : @escaping ((_ responseURL : URL?) -> Void)){
    if self.mediaType == .image {
        let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
        options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData) -> Bool in
            return true
        }
        self.requestContentEditingInput(with: options, completionHandler: {(contentEditingInput: PHContentEditingInput?, info: [AnyHashable : Any]) -> Void in
            completionHandler(contentEditingInput!.fullSizeImageURL as URL?)
        })
    } else if self.mediaType == .video {
        let options: PHVideoRequestOptions = PHVideoRequestOptions()
        options.version = .original
        PHImageManager.default().requestAVAsset(forVideo: self, options: options, resultHandler: {(asset: AVAsset?, audioMix: AVAudioMix?, info: [AnyHashable : Any]?) -> Void in
            if let urlAsset = asset as? AVURLAsset {
                let localVideoUrl: URL = urlAsset.url as URL
                completionHandler(localVideoUrl)
            } else {
                completionHandler(nil)
            }
        })
      }
    }
  }
Obi
  • 7
  • 1
  • 3
  • Above code will not work while uploading video/image url directly to server. First, fetch the video/image from PHAsset and then storing that to local file path to upload it to server. Please check this link: https://stackoverflow.com/questions/38381851/how-to-upload-phasset-video-and-image-only? – Sagar Sukode Jan 15 '21 at 10:20