2017-04-19 84 views
0

我試圖通過發送文件的ID從服務器下載文件。我嘗試了幾件事,但該文件正在下載爲CFNetworkDownload.tmp文件。Swift下載任務請求文件下載不起作用

我希望它保存爲存在的文件。文件類型可以是PNG,JPEG,PDF,DOCX,PPTX,XLSX。嘗試了很多事情,但徒勞無功。我敢肯定它一定是簡單的東西,我很想在這裏明白

試過以下。在大多數例子中,差異是文件名在URL中。但我發送id並獲取文件作爲迴應。

How to download file in swift?

How To Download Multiple Files Sequentially using NSURLSession downloadTask in Swift

下面是我的代碼。

func downloadFile(id : String, fileName : String) -> Void { 


    let session = URLSession.shared 
    let url = URL(string: qaDownloadURL+id)! 

    var request = URLRequest(url: url) 
    request.httpMethod = "POST" 

    let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in 
     if let tempLocalUrl = tempLocalUrl, error == nil { 
      // Success 
      if let statusCode = (response as? HTTPURLResponse)?.statusCode { 
       print("Success: \(statusCode)") 
      } 

      do { 



//     let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first 
//      
//     self.savePath = documentsUrl!.absoluteString + "/" + fileName 
//      
//     let fileURL = URL(fileURLWithPath: self.savePath) 
//      
//     let dataFromURL = NSData(contentsOf: tempLocalUrl) 
//     dataFromURL?.write(to: fileURL, atomically: true) 

       var documentsDirectory: String? 

       let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) 

       if paths.count > 0 
       { 
        documentsDirectory = paths.first! 
       } 

       self.savePath = documentsDirectory!// + "/" + fileName 

       let fileURL = URL(fileURLWithPath: self.savePath) 


       let dataFromURL = NSData(contentsOf: tempLocalUrl) 
       dataFromURL?.write(to: fileURL, atomically: true) 


       // try FileManager.default.copyItem(at: tempLocalUrl, to: fileURL) 


       DispatchQueue.main.async { 

        let documentController = UIDocumentInteractionController.init(url: fileURL) 
        documentController.delegate = self 
        documentController.presentPreview(animated: true) 

       } 

      } catch (let writeError) { 
       print("error writing file \(self.savePath) : \(writeError)") 
      } 

     } else { 
      print("Failure: %@", error?.localizedDescription); 
     } 
    } 
    task.resume() 

} 
+0

是的,我剛剛也試過。不起作用:( –

+0

問題是你使用「POST」方法而不是「GET」。順便說一句,你應該只使用一個URL。當你只想獲得某些東西(不是POST)時不需要使用URLRequest –

+0

順便說一句應該幫助http://stackoverflow.com/a/27643660/2303865 –

回答

1

不能寫入數據到它代表一個目錄的位置,你需要指定的完整路徑,包括文件名。

利用現代URL相關的API,你可以用

do { 
      let documentFolderURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) 
      let fileURL = documentFolderURL.appendingPathComponent(fileName) 
      try FileManager.default.copyItem(at: tempLocalUrl, to: fileURL) 

      DispatchQueue.main.async { 

       let documentController = UIDocumentInteractionController.init(url: fileURL) 
       documentController.delegate = self 
       documentController.presentPreview(animated: true) 

      }  
     } 

更換整個do塊或使用URLSessionDataTask返回原始數據,而不是將文件下載到一個臨時位置,並直接保存Data例如

let task = session.dataTask(with: request) { (data, response, error) in 
    guard error == nil else { 
     print(error!) 
     return 
    } 
    // Success 
    if let statusCode = (response as? HTTPURLResponse)?.statusCode { 
     print("Success: \(statusCode)") 
    } 

    do { 
     let documentFolderURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) 
     let fileURL = documentFolderURL.appendingPathComponent(fileName) 
     try data!.write(to: fileURL) 

     DispatchQueue.main.async { 

      let documentController = UIDocumentInteractionController.init(url: fileURL) 
      documentController.delegate = self 
      documentController.presentPreview(animated: true) 

     } 

    } catch { 
     print("error writing file \(fileName) : \(error)") 
    } 
} 
task.resume() 

如果這不起作用,則錯誤與其他地方有關。

+0

但爲什麼它下載tempLocalUrl .tmp文件?任何想法? –

+0

我試過URLSessionDataTask並保存數據,它的工作,你可以多描述一下,這樣我就可以接受這個答案 –

+0

@SharanyaKM問題是你使用「POST」方法,而不是「GET」,順便說一句,你應該只使用一個URL。 URLRequest當你只是想獲得一些東西(不是POST) –

0

你可以這樣做:

/************************************************************************** 
    TAP FOR DOWNLOAD : DOWNLOAD REMOTE DATA AND SAVE TO DOC DIRECTORY 
    ***************************************************************************/ 
    cell.loadingIcon.startAnimating() 
    let indexPath = self.songTableView.indexPath(for: cell) 
    let song = filteredList?.object(at: (indexPath?.row)!) as! CKSong 

    let songURL = NSURL(string : song.url as! String) 

    let downloadTask : URLSessionDownloadTask = self.downloadsSession.downloadTask(with: songURL as! URL) { (location, response, error) in 

     if (error == nil) { 

      let time = NSNumber(value:(NSDate().timeIntervalSince1970 * 1000)) 
      let fileName = NSString(format:"%@_music.mp3",time) 
      let documentsUrl:URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL! 
      let destinationFileUrl = documentsUrl.appendingPathComponent(fileName as String) 

      do { 
       try FileManager.default.copyItem(at: location!, to: destinationFileUrl) 
      } catch (let writeError) { 
       print("Error creating a file \(destinationFileUrl) : \(writeError)") 
      } 

      print("DOWNLOAD FINISHED \(location)") 
      print("DOWNLOAD FINISHED \(destinationFileUrl)") 

      song.localURL = destinationFileUrl.path as NSString? 
     } 
     DispatchQueue.main.async { 
      cell.playButton.isEnabled = (song.localURL != nil) 
      cell.loadingIcon.stopAnimating() 
     } 
    } 

    downloadTask.resume() 
} 

//==================================================================================================================================== 
// SONG DOWNLOAD TASK : NSURLSESSION 
//==================================================================================================================================== 

lazy var downloadsSession: URLSession = { 
    let configuration = URLSessionConfiguration.default 
    let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil) 
    return session 
}() 

希望這有助於。

參考:https://github.com/Abhishek9634/CokeStudio/blob/CHANGE_BRANCH/CokeStudio/CokeStudio/CKSongsListVC.swift#L164

+0

沒有...這不工作... –