0
votes

In my app, showing all videos from photos. When a video is selected, it is played with avplayer. But when i tried to get the size (kb) of the selected video file, it shows error. The same error appeared when i tried to copy the video file.

I have taken those permissions:

<key>NSCameraUsageDescription</key>
<string>App needs to access camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>App need to access microphone</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>App needs to access photos and videos</string>

Code to get size:

func fileSize(forURL url: Any) -> Double {

    var fileURL: URL?
    var fileSize: Double = 0.0

    if url is URL || url is String {

        if url is URL {
            fileURL = url as? URL
        }
        else {
            fileURL = URL(fileURLWithPath: url as! String)
        }
        var fileSizeValue = 0.0

        do{
            try fileSizeValue = (fileURL?.resourceValues(forKeys: [URLResourceKey.fileSizeKey]).allValues.first?.value as! Double?)!
            if fileSizeValue > 0.0 {
                fileSize = (Double(fileSizeValue) / (1024 * 1024))
            }

        } catch {

            print("file size error: \(error)")
        }
    }
    return fileSize
}

let fileSize = fileSize(forURL: selectedVideos[0] as Any)

video file url: "file:///var/mobile/Media/DCIM/107APPLE/IMG_7728.MOV"

Error: Error Domain=NSCocoaErrorDomain Code=257 "The file “IMG_7728.MOV” couldn’t be opened because you don’t have permission to view it." UserInfo={NSURL=file:///var/mobile/Media/DCIM/107APPLE/IMG_7728.MOV, NSFilePath=/var/mobile/Media/DCIM/107APPLE/IMG_7728.MOV, NSUnderlyingError=0x1c445ef90 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}

Edit: I have changed url to path. But still shows error:

   let selectedFilePath = (selectedVideos[0] as! URL).path
    print("video path: \(selectedFilePath)")
    do{
        let attributes = try FileManager.default.attributesOfItem(atPath: selectedFilePath)
        let fileSize = attributes[.size] as! NSNumber
        print("file size: \(fileSize)")
    } catch {  
        print("file size error: \(error)")
    }

    let filePath = get_directory().appendingPathComponent("video\(CACurrentMediaTime()).MOV")
    print("copy to path: \(filePath.path)")
    do {
        try FileManager.default.copyItem(atPath: selectedFilePath, toPath: filePath.path)

    } catch {

        print("copy error: \(error)")
    }

Error:

video path: /var/mobile/Media/DCIM/107APPLE/IMG_7789.MOV

file size error: Error Domain=NSCocoaErrorDomain Code=257 "The file “IMG_7789.MOV” couldn’t be opened because you don’t have permission to view it." UserInfo={NSFilePath=/var/mobile/Media/DCIM/107APPLE/IMG_7789.MOV, NSUnderlyingError=0x1c0259530 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}

copy to path: /var/mobile/Containers/Data/Application/5AAD29BD-489D-4737-AA98-E6131EFBA94D/Documents/addMusicToVideos/voices/video1171047.69338271.MOV

copy error: Error Domain=NSCocoaErrorDomain Code=257 "The file “IMG_7789.MOV” couldn’t be opened because you don’t have permission to view it." UserInfo={NSFilePath=/var/mobile/Media/DCIM/107APPLE/IMG_7789.MOV, NSUnderlyingError=0x1c4859830 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}

1
you have to use url.pathPiterPan
thanks bro, i have changed but still showing error. I have added info about this in question.Sarwar Jahan
Unrelated but why is url Any although only URL or String is expected? That's horrible. Do your homework at design time and declare the type as URL. Then the compiler will tell you all places where you are going to pass a string (or something else) and you can fix the code by creating the URL before calling the function. This avoids the unnecessary and expensive runtime check. Even a second function which takes a string, creates the URL and calls the function is much more efficient.vadian
@vadian yeah, agreed with u. But i have to keep this for the purpose of my app. :(Sarwar Jahan
What are you using to select the movie? Is it UIDocumentPickerController?Leo Dabus

1 Answers

0
votes

You can get a size of a video file from an URL very easily by using this AVURLAsset extension. Make sure to import AVFoundation framework. The code is given below:

extension AVURLAsset {
    var fileSize: Int? {
    let keys: Set<URLResourceKey> = [.totalFileSizeKey, .fileSizeKey]
    let resourceValues = try? url.resourceValues(forKeys: keys)

    return resourceValues?.fileSize ?? resourceValues?.totalFileSize
    }
} 

This extension returns the video size in Int(bytes). you can modify the units as you need. To call it, use this approach:

let asset = AVURLAsset(url: urlOfYourAsset)
print(asset.fileSize ?? 0)

You didn't give sufficient information. The problem is with your file system. Where you put the video files in iOS matters and how you get the URL, that is the problem. Maybe its your URL that is not permitted in a sandbox. Please study further and read Apple Documentation.