Export files from Music Library to Documents directory (Swift 5)

615 views Asked by At

In my app I want to export files from Music Library and save them to Documents directory. I already fetch file list from Music Library and I get url of each file. But I still have two problems:

  1. I can export files only in "m4a" format, but I'd like to export it in format what file was in Music Library (mp3, wav, aac or else)

  2. How can I save files from Music Library to Documents directory with url? My code now looks like this:

     private func exportFile(with assetURL: URL, completionHandler: @escaping (_ fileURL: URL?, _ error: Error?) -> ()) {
         let asset = AVURLAsset(url: assetURL)
         guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else {
             completionHandler(nil, nil)
             return
         }
    
         let fileURL = URL(fileURLWithPath: NSTemporaryDirectory())
             .appendingPathComponent(NSUUID().uuidString)
             .appendingPathExtension("m4a")
    
         exporter.outputURL = fileURL
         exporter.outputFileType = AVFileType.m4a
    
         exporter.exportAsynchronously {
             if exporter.status == .completed {
                 completionHandler(fileURL, nil)
             } else {
                 completionHandler(nil, exporter.error)
             }
         }
    
    func downloadFile(file: MPMediaItem?, callback: @escaping () -> ()) {
         guard let file = file,
               let url = file.url
         else { return }
         exportFile(with: url) { fileURL, error in
             guard let fileURL = fileURL, error == nil else {
                 print(error?.localizedDescription)
                 return
             }
    
             //Here I'd like to save file to Documents dir
             print("\(fileURL)")
         }
         callback()
       }
    
1

There are 1 answers

0
Oranutachi On

Solution for second question.

I put the code in one method and save directly to the Documents folder, not to a temporary folder:

func downloadFile(file: MPMediaItem?, callback: @escaping () -> ()) {
        guard let file = file,
              let url = file.assetURL
        else { return }
        let exportSession = AVAssetExportSession(asset: AVAsset(url: url), presetName: AVAssetExportPresetAppleM4A)
        exportSession?.shouldOptimizeForNetworkUse = true
        exportSession?.outputFileType = AVFileType.m4a
        
        let documentURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        let outputURL = documentURL.appendingPathComponent("\(file.title!).m4a")
        //        //Delete Existing file if needs
        //        do {
        //              try FileManager.default.removeItem(at: outputURL)
        //        } catch let error as NSError {
        //              print(error.debugDescription)
        //        }
        exportSession?.outputURL = outputURL
        exportSession?.exportAsynchronously(completionHandler: { () -> () in
            
            if exportSession!.status == AVAssetExportSession.Status.completed  {
                print("Export Successful")
                DispatchQueue.main.async {
                    //Update IU
                    callback()
                }
            } else {
                print("Export failed")
            }
        })
    }