2

So I am accessing the user's videos & photos through a custom UICollectionView, my issue is that when I attempt to upload to firebase the video through the mobile phone, i am getting this error:

2017-09-03 13:09:20.884509-0400 Project[5797:2021536] Cannot get file size: Error Domain=NSCocoaErrorDomain Code=257 "The file “IMG_3476.MP4” couldn’t be opened because you don’t have permission to view it." UserInfo={NSURL=file:///var/mobile/Media/DCIM/103APPLE/IMG_3476.MP4, NSFilePath=/var/mobile/Media/DCIM/103APPLE/IMG_3476.MP4, NSUnderlyingError=0x17064f450 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
  /var/mobile/Media/DCIM/103APPLE/IMG_3476.MP4
2017-09-03 13:09:21.261767-0400 Project[5797:2021536] Body file is unreachable: /var/mobile/Media/DCIM/103APPLE/IMG_3476.MP4
  Error Domain=NSCocoaErrorDomain Code=257 "The file “IMG_3476.MP4” couldn’t be opened because you don’t have permission to view it." UserInfo={NSURL=file:///var/mobile/Media/DCIM/103APPLE/IMG_3476.MP4, NSFilePath=/var/mobile/Media/DCIM/103APPLE/IMG_3476.MP4, NSUnderlyingError=0x170651b20 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}

Here is where I am loading the files

struct Media {
    var image:UIImage?
    var videoURL:NSURL?
}

var mediaArray = [Media]()

func grabPhotos(){
    let imgManager = PHImageManager.default()

    let requestOptions = PHImageRequestOptions()
    requestOptions.isSynchronous = true
    requestOptions.deliveryMode = .highQualityFormat

    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions) {


        if fetchResult.count > 0 {
            for i in 0..<fetchResult.count{
                var mediaItem = Media()
                //Used for fetch Image//
                imgManager.requestImage(for: fetchResult.object(at: i) as PHAsset , targetSize: CGSize(width: 400, height: 400), contentMode: .aspectFit, options: requestOptions, resultHandler: {
                    image, error in
                    let imageOfVideo = image! as UIImage
                    mediaItem.image = imageOfVideo;
                    //Used for fetch Video//
                    imgManager.requestAVAsset(forVideo: fetchResult.object(at: i) as PHAsset, options: PHVideoRequestOptions(), resultHandler: {(avAsset, audioMix, info) -> Void in
                        if let asset = avAsset as? AVURLAsset {
                            let videoData = NSURL(string: "\(asset.url)")
                            let duration : CMTime = asset.duration
                            let durationInSecond = CMTimeGetSeconds(duration)
                            print(durationInSecond)
                            mediaItem.videoURL = videoData!
                            self.mediaArray.append(mediaItem)
                            print(self.mediaArray.count)


                        }

                    })
                })
            }

        }
        else{
            //showAllertToImportImage()//A function to show alert
        }
    }
}

I dont think it has to do with when I am uploading the video because i can record a video an upload it from the phone, just not upload from the phone itself; I am just transferring over the url to the nextVC like so:

let videoVC = PrepareVideoVC()
        videoVC.url = outputFileURL as URL!
        self.navigationController?.pushViewController(videoVC, animated: false)

I looked into this The file “ ” couldn’t be opened because you don’t have permission to view it but couldnt really figure out how to implement it

I also came across https://stackoverflow.com/a/41517165/7823620 but once again I tried implementing it but couldnt get it to not give me errors

Also I can upload from the simulator but not the mobile phone

It is trying to get a file from this directory:

NSFilePath=/var/mobile/Media/DCIM/
AndrewS
  • 351
  • 4
  • 18

3 Answers3

7

You can try

url.startAccessingSecurityScopedResource()
<...>
url.stopAccessingSecurityScopedResource()
Ivan Vavilov
  • 1,520
  • 1
  • 15
  • 28
0

use this options:

PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
options.version = PHVideoRequestOptionsVersionCurrent;
options.deliveryMode = PHVideoRequestOptionsDeliveryModeHighQualityFormat;
options.networkAccessAllowed = true;

if you request the middle-quality video, then u will get an error " Error Domain=NSCocoaErrorDomain Code=257, no permission..."

0

So if the AppDelegate gets passed in a document on launch via this method:

 func application(_: UIApplication, open url: URL, options _: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {

I found that I had to do this to FIX it so that FileManager documents loaded successfully using Ivan's solution above but you CAN NOT make that call if say the document is an e-mail attachment.

This fixed it for me and huge thanks again to Ivan Vavilov for his post.

func application(_: UIApplication, open url: URL, options _: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
    print("Doc attachment passed")
    let docAttachment = url
    
    // files written to 'tmp' are NOT backed up to iCloud or iTunes
    let tempDir = getTempDirectory()
    
    // add file name to tmp path
    tempFileToLoad = tempDir.appendingPathComponent(docAttachment.lastPathComponent)

    let fm = FileManager()
    
    // passed a file from the FileManger app?
    let isAttachmentScopedResource = docAttachment.startAccessingSecurityScopedResource()
    
    do {
        
        // put in tmp so we can read/write
        try fm.copyItem(at: docAttachment, to: tempFileToLoad!)
        
        if(isAttachmentScopedResource) {
            // have MUST release the security access after calling it
            docAttachment.stopAccessingSecurityScopedResource()
        }
        
    } catch {
        print("Error getting file.  \(error)")
        return false
    }
Waxhaw
  • 599
  • 5
  • 9