How much can Document Directory in FileManager hold? - swift

I'v built an app that lets the user record their voice and save the file in their local Document Directory (They can create/save as many audio files they choose too).
But recently Iv into the problem where after a certain amount of saves it seems my function to save does not work on my simulator until i reset the simulator data. Then it will work again.
I also tried it on my own iPhone..it was working where the user can create/save and listen to their audio but now it wont let them listen to it but saving works fine from what I can tell.
Here are the related codes!
func tableView(tableView: UITableView,
editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let play = UITableViewRowAction(style: .Default, title: "Play", handler: { (action, indexPath) in
self.tableView.dataSource?.tableView?(
self.tableView,
commitEditingStyle: .Delete,
forRowAtIndexPath: indexPath
)
let dispatchQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(dispatchQueue, {
let url = self.sharedRec.audioDic[indexPath.row]["audioURL"] as String!
let kingURL = "\(url)"
print(kingURL)
if let data = NSData(contentsOfFile: kingURL) {
do {
print("PLAYING AUDIO WORKED!") // NOT WORKING ANYMORE
self.audioPlayer = try AVAudioPlayer(data: data)
self.audioPlayer.delegate = self
self.audioPlayer.prepareToPlay()
self.audioPlayer.play()
// Progress View Code
NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: #selector(RecordPanel.updateAudioProgressView), userInfo: nil, repeats: true)
} catch {
print("ERROR BOY \(kingURL)")
print("\(error)")
}
}
})
print("I PLAYED")
return
})
let pause = UITableViewRowAction(style: .Default, title: "Pause", handler: { (action, indexPath) in
self.tableView.dataSource?.tableView?(
self.tableView,
commitEditingStyle: .Delete,
forRowAtIndexPath: indexPath
)
if let player = self.audioPlayer {
player.pause()
}
return
})
let delete = UITableViewRowAction(style: .Default, title: "Delete", handler: { (action, indexPath) in
self.tableView.dataSource?.tableView?(
self.tableView,
commitEditingStyle: .Delete,
forRowAtIndexPath: indexPath
)
let uid = NSUserDefaults.standardUserDefaults().valueForKey("uid") as! String // uid
DataService.dataService.deleteAudio(uid, project: self.sharedRec.projectName, vocalString: self.sharedRec.audioString )
let currURL = self.sharedRec.audioString
let url = "\(currURL).caf"
//Document Directory
let dirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
// Full File to Delete Location
let fileURL = dirPath.stringByAppendingPathComponent(url)
// This is to print out all directory files
let documentsUrl = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
do {
try NSFileManager.defaultManager().removeItemAtPath(fileURL)
print("file deleted \(fileURL)")
let directoryContents = try NSFileManager.defaultManager().contentsOfDirectoryAtURL(documentsUrl, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions())
print(directoryContents)
} catch {
print("error")
}
return
})

Related

Program on Swift Crashes when first compiling

So I ran this code using swift and the issue that I am having is that it's not working on the first try it compiles the project. However, when I stop the project and run it again it works perfectly fine and I do repeat this several times and the issue doesn't occur anymore. More specifically, when the project opens and I press a button on the app it goes to the error that I show below:
This is the error that I get when I run it for the first time
"Thread 1: Fatal error: 'try!' expression unexpectedly raised an
error: Error Domain=NSCocoaErrorDomain Code=260 "The file “.tmp”
couldn’t be opened because there is no such file."
UserInfo={NSFilePath=/.tmp, NSUnderlyingError=0x60000335d9b0 {Error
Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}"
This error shows up on the line where let contentstring is created. I check the value of contentstring and I get that contentstring = (NSString) 0x0000000000000000. When running the program multiple times it gives me a valid value and it works perfectly fine.
I am not sure why this error occurs only once when the button is pressed and what is a solid approach to this problem.
import UIKit
class KresgePorter: UIViewController, UITableViewDataSource, UITableViewDelegate {
var printString: String!
var array: [String] = []
var count: Int = 0
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: false)
}
override func viewDidLoad() {
super.viewDidLoad()
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
var nameTXT = ""
var documentsDir = ""
let website = some string url
guard let url1 = URL(string: website) else { return }
//This portion of the code focuses on creating a download task with a completion handler
//Completion handler moves the downloaded file to the app's directory
let downloadTask = URLSession.shared.downloadTask(with: url1) {
urlOrNil, responseOrNil, errorOrNil in
// check for and handle errors:
// * errorOrNil should be nil
// * responseOrNil should be an HTTPURLResponse with statusCode in 200..<299
print("Went into the let\n")
guard let fileURL = urlOrNil else { return }
do {
let documentsURL = try
FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true)
let savedURL = documentsURL.appendingPathComponent(fileURL.lastPathComponent)
let filename = fileURL.lastPathComponent
let fileName2 = URL(fileURLWithPath: filename).deletingPathExtension().lastPathComponent
nameTXT = fileName2
print("the content of nameTXT is: \(nameTXT)")
try FileManager.default.moveItem(at: fileURL, to: savedURL)
} catch {
print ("file error: \(error)")
}
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray
documentsDir = paths.firstObject as! String
print("Path to the Documents directory\n\(documentsDir)")
}
downloadTask.resume()
//If you want to receive progress updates as the download proceeds, you must use a delegate.
var urlSession = URLSession(configuration: .default, delegate: self as? URLSessionDelegate, delegateQueue: nil)
func startDownload(url1: URL){
print("Went into the startDownload function\n")
let downloadTask = urlSession.downloadTask(with: url1)
//let fname = downloadTask.response?.suggestedFilename
downloadTask.resume()
}
startDownload(url1: url1)
/*-----------------------------------------------------------------------------------------------------*/
usleep(270000)
let directPath = documentsDir + "/" + nameTXT + ".tmp"
let url = URL(fileURLWithPath: directPath)
let contentString = try! NSString(contentsOf: url, encoding: String.Encoding.utf8.rawValue)
printString = contentString as String
let fullName = printString
array = fullName!.components(separatedBy: "\n")
// Do any additional setup after loading the view.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "breakfast", for: indexPath)
cell.textLabel?.text = array[indexPath.row]
return cell
}
}
I shouldn't use try! in production code!
let contentString = try! NSString(contentsOf: url, encoding: String.Encoding.utf8.rawValue)
convert to this:
do {
let contentString = try? String( url, encoding: .utf8)
} catch {
print(error)
}
The actual problem is that:
let directPath = documentsDir + "/" + nameTXT + ".tmp"
let url = URL(fileURLWithPath: directPath)
yields "/.tmp". this is an invalid URL.
This is because of both documentsDir and nameTXT are empty.
So, the core reason is that you call
let directPath = documentsDir + "/" + nameTXT + ".tmp"
let url = URL(fileURLWithPath: directPath)
outside of the server response callback.
Just move your code from
// If you want to receive progress updates as the download until
array = fullName!.components(separatedBy: "\n")
into closure right after this line:
print("Path to the Documents directory\n\(documentsDir)")
your closure is launched asynchronously.

PDF view not presenting

I'm downloading a PDF from a url and then displaying it using PDFKit in Swift5. However, when I tap my viewCell it is not presenting the PDF and potentially not downloading the PDF. How can I verify this?
I have two files, PlanogramViewController and ShowPDFViewController.
var pdfURL: URL!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let plano = self.data[indexPath.row] as? Planogram {
guard let url = URL(string: Plano.pdfUrl) else { return }
let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
let downloadTask = urlSession.downloadTask(with: url)
downloadTask.resume()
let pdfViewController = ShowPDFViewController()
pdfViewController.pdfURL = self.pdfURL
present(pdfViewController, animated: false, completion: nil)
tableView.deselectRow(at: indexPath, animated: true)
}
}
extension PlanogramViewController: URLSessionDownloadDelegate {
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("downloadLocation:", location)
// create destination URL with the original pdf name
guard let url = downloadTask.originalRequest?.url else { return }
let documentsPath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
let destinationURL = documentsPath.appendingPathComponent(url.lastPathComponent)
// delete original copy
try? FileManager.default.removeItem(at: destinationURL)
// copy from temp to Document
do {
try FileManager.default.copyItem(at: location, to: destinationURL)
self.pdfURL = destinationURL
} catch let error {
print("Copy Error: \(error.localizedDescription)")
}
}
}
So I'm not getting any download verification from my extension. It should be printing my initial download location and then moving it to the cache. If it encounters an error it should also print an error, but I'm getting nothing in the console. As if nothing is downloading.
Then here is the pdfViewController it's supposed to present once it has the PDF downloaded:
import UIKit
import PDFKit
class ShowPDFViewController: UIViewController {
var pdfView = PDFView()
var pdfURL: URL!
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(pdfView)
if let document = PDFDocument(url: pdfURL) {
pdfView.document = document
}
DispatchQueue.main.asyncAfter(deadline: .now()+3) {
self.dismiss(animated: true, completion: nil)
}
}
override func viewDidLayoutSubviews() {
pdfView.frame = view.frame
}
}
The current behavior is it just highlights the cell I tapped. Nothing in the console and nothing presented on the display.
You need to conform to the UITableViewDelegate and UITableViewDataSourceDelegate protocols in the view controller that has the tableView.
and add
tableView.delegate = self
tableView.dataSource = self
in the viewDidLoad()
Then, implement the required methods, and add optional methods to further customize your tableView.

NSFileManager fails to save - No such file or directory

I'm using 'AlamoFireImage' to download my image files.
And after that, I use NSFileManager and CreateFile method to save them in a directory.
But when I try to retrieve the saved images, It only returns the first File. While It should have saved 15 images.
Here's my function for saving Image Files :
func getImage(url: String) {
Alamofire.request("https://www.tandori.ir/uploads/categories/" + url).responseImage { (response) in
if response.result.value != nil {
do {
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(url)
let image = UIImage(named: url)
let imageData = image?.jpegData(compressionQuality: 0.2)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
print(paths)
}
catch let error as NSError {
print(error)
}
}
}
}
And this is my function for downloading them :
func launchApp() {
let imgTitiles = UserDefaults.standard.array(forKey: "imgsArray")!
for pic in imgTitiles {
self.getImage(url: pic as! String)
print("done")
}
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let resultViewController = storyBoard.instantiateViewController(withIdentifier: "mainTab") as! TandoriTabView
self.present(resultViewController, animated: true)
}
When I try to retrieve the saved images, I get this error on Console :
"BOMStream BOMStreamWithFileAndSys(int, off_t, size_t, int, char *, BomSys *): read: No such file or directory"
I'm trying to Show these images in a collection view.
Here's my code in my ViewController :
//Get Images Directory Path Function.
func getDirectoryPath() -> String {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
//Get Images Function.
func getImage(name : String) -> String {
_ = FileManager.default
let imagePAth = (self.getDirectoryPath() as NSString).appendingPathComponent(name)
return imagePAth
}
//Show Images in collectionView cells function.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = categoriesCollection.dequeueReusableCell(withReuseIdentifier: "categories", for: indexPath) as! categoriesCell
let imageAddress = getImage(name: imgTitiles[indexPath.row] as! String) //TheRealShit
cell.categoryImage.image = UIImage(contentsOfFile: imageAddress)
return cell
}
What seems to be the Problem?
Thanks in advance!
Actually your using Alamofire downloading images are in asynchronously. Due to this you are only few images when you are showing viewcontroller. Modify your code to getImage() synchronously in below code. I hope it will work for you.
func getImage(url: String) {
if let image = UIImage(named: url) {
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(url)
let imageData = image?.jpegData(compressionQuality: 0.2)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
print(paths)
}
}

Swift - Automatically save pdf file to Files app On My iPhone

I am in desperate need of help.
I am trying to create an app which allows the user to save the pdf file from a link such as the example one I gave in the subjectLinks array, all those links point to a pdf page and I am trying to download it and save it in my app. So far, I have scoured everywhere and found a way to do it using the Files app, so what I'm doing in the code is downloading the data of the pdf and opening it using UIDocument and presentPreview to display it and I have managed to allow the user to share the downloaded file and save it to Files as well.
However the problem arises as I want to make it so that when the user clicks download the file is automatically saved to the Files app in a directory so that the user does not need to click the option button then choose Save to Files and then look for where to save it. Is that possible??
If that is not possible, at least when the user chooses the option button and clicks Save to Files, it would automatically create a separate directory where the user can see and pdf file can be saved?
I want to do this as most times, when Save to Files is chosen, saving 'On My iPhone' is not available as there is no directory or such present so it can only be saved to google drive or iCloud Drive and this is a major inconvenience.
Sorry for the long post. BUT I WOULD BE EXTREMELY GRATEFUL IF ANYONE COULD HELP SOLVE MY PROBLEM. THANK YOU SOOOOO MUCH IN ADVANCE :)
P.S everything in my code works perfectly fine so far, its just I am absolutely clueless as to how to implement the features I have outlines above?
import UIKit
import StoreKit
class TableViewController: UITableViewController {
let documentInteractionController = UIDocumentInteractionController()
let subjectLinks = ["https://pastpapers.papacambridge.com/Cambridge%20International%20Examinations%20(CIE)/AS%20and%20A%20Level/Accounting%20(9706)/2015%20Jun/9706_s15_qp_42.pdf", "https://pastpapers.papacambridge.com/Cambridge%20International%20Examinations%20(CIE)/AS%20and%20A%20Level/Economics%20(9708)/2017%20Jun/9708_s17_qp_12.pdf", "https://pastpapers.papacambridge.com/Cambridge%20International%20Examinations%20(CIE)/AS%20and%20A%20Level/Mathematics%20(9709)/2018-May-June/9709_s18_qp_12.pdf"]
override func viewDidLoad() {
super.viewDidLoad()
documentInteractionController.delegate = self as? UIDocumentInteractionControllerDelegate
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return subjectLinks.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = subjectLinks[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
{
// 1
let shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Download" , handler: { (action:UITableViewRowAction, indexPath: IndexPath) -> Void in
// 2
let downloadMenu = UIAlertController(title: nil, message: "Download this paper", preferredStyle: .actionSheet)
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
downloadMenu.addAction(UIAlertAction(title: "Download", style: UIAlertActionStyle.destructive, handler: { action in self.storeAndShare(withURLString: self.subjectLinks[indexPath.row])}))
downloadMenu.addAction(cancelAction)
self.present(downloadMenu, animated: true, completion: nil)
})
// 3
let rateAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Rate" , handler: { (action:UITableViewRowAction, indexPath:IndexPath) -> Void in
// 4
let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .actionSheet)
let appRateAction = UIAlertAction(title: "Rate", style: UIAlertActionStyle.default, handler: {action in SKStoreReviewController.requestReview()})
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
rateMenu.addAction(appRateAction)
rateMenu.addAction(cancelAction)
self.present(rateMenu, animated: true, completion: nil)
})
// 5
return [shareAction,rateAction]
}
}
extension TableViewController {
/// This function will set all the required properties, and then provide a preview for the document
func share(url: URL) {
documentInteractionController.url = url
documentInteractionController.uti = url.typeIdentifier ?? "public.data, public.content"
documentInteractionController.name = url.localizedName ?? url.lastPathComponent
documentInteractionController.presentPreview(animated: true)
}
/// This function will store your document to some temporary URL and then provide sharing, copying, printing, saving options to the user
func storeAndShare(withURLString: String) {
guard let url = URL(string: withURLString) else { return }
/// START YOUR ACTIVITY INDICATOR HERE
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else { return }
let fileManager = FileManager.default
do {
let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
let fileURL = documentDirectory.appendingPathComponent("fileName.pdf")
try data.write(to: fileURL)
DispatchQueue.main.async {
self.share(url: fileURL)
}
} catch {
print(error)
}
}.resume()
}
}
extension TableViewController: UIDocumentInteractionControllerDelegate {
/// If presenting atop a navigation stack, provide the navigation controller in order to animate in a manner consistent with the rest of the platform
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
guard let navVC = self.navigationController else {
return self
}
return navVC
}
}
Example of download any pdf file and automatically save inside files folder of iPhone.
let urlString = "https://www.tutorialspoint.com/swift/swift_tutorial.pdf"
let url = URL(string: urlString)
let fileName = String((url!.lastPathComponent)) as NSString
//Mark: Create destination URL
let documentsUrl:URL = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL?)!
let destinationFileUrl = documentsUrl.appendingPathComponent("\(fileName)")
//Mark: Create URL to the source file you want to download
let fileURL = URL(string: urlString)
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:fileURL!)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
//Mark: Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
}
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
do {
//Mark: Show UIActivityViewController to save the downloaded file
let contents = try FileManager.default.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
for indexx in 0..<contents.count {
if contents[indexx].lastPathComponent == destinationFileUrl.lastPathComponent {
let activityViewController = UIActivityViewController(activityItems: [contents[indexx]], applicationActivities: nil)
self.present(activityViewController, animated: true, completion: nil)
}
}
}
catch (let err) {
print("error: \(err)")
}
} catch (let writeError) {
print("Error creating a file \(destinationFileUrl) : \(writeError)")
}
} else {
print("Error took place while downloading a file. Error description: \(error?.localizedDescription ?? "")")
}
}
task.resume()
Step #1: Need to add permission in info.plist
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
Step #2: Download document from server url[any document]
func downloadPdf(sender:UIButton) {
DispatchQueue.main.async {
//Do UI Code here.
let pdfUrl = self.myOrderListModel?.myorderList?[sender.tag].invoiceUrl ?? ""
guard let fileURL = URL(string: pdfUrl) else { return }
var originalUrlStr : String = ""
print(fileURL.pathExtension)
if fileURL.pathExtension == ""{
originalUrlStr = pdfUrl + ".pdf"
} else {
originalUrlStr = pdfUrl
}
guard let originalUrl = URL(string: originalUrlStr) else { return }
let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
let downloadTask = urlSession.downloadTask(with: originalUrl)
downloadTask.resume()
}
}
extension InvoiceViewController: URLSessionDownloadDelegate {
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("File Downloaded Location- ", location)
guard let url = downloadTask.originalRequest?.url else {
return
}
let docsPath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
let destinationPath = docsPath.appendingPathComponent(url.lastPathComponent)
try? FileManager.default.removeItem(at: destinationPath)
do{
try FileManager.default.copyItem(at: location, to: destinationPath)
print("File Downloaded Location- ", destinationPath)
DispatchQueue.main.async {
let urlString: String = destinationPath.absoluteString
self.saveInvoiceToDevice(filePath: urlString)
}
}catch let error {
print("Copy Error: \(error.localizedDescription)")
}
}
}
Step #3: Save downloaded file in Device "Files" Folder
func saveInvoiceToDevice(filePath : String) {
let fileURL = URL(string: filePath)
if FileManager.default.fileExists(atPath: fileURL!.path){
let url = URL(fileURLWithPath: fileURL!.path)
let activityViewController: UIActivityViewController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView=self.view
//If user on iPad
if UIDevice.current.userInterfaceIdiom == .pad {
if activityViewController.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
}
}
self.present(activityViewController, animated: true, completion: nil)
}
else {
debugPrint("document was not found")
}
}

Setting Alamofire custom destination file name instead of using suggestedDownloadDestination

I got many lists of invoice file at my table view as well as many download buttons at each cell.When I clicked one of it,it will download the invoice file.But,the problem is the server response suggested file name is "invoice.pdf" at every file I downloaded.So,I need to edit the file name manually before I save to document after it was downloaded.So,how to edit the file name manually after it was download successfully and save it in document as temporaryurl without using Alamofire.Request.suggestedDownloadDestination.
Here is my download function.
func downloadInvoice(invoice: Invoice, completionHandler: (Double?, NSError?) -> Void) {
guard isInvoiceDownloaded(invoice) == false else {
completionHandler(1.0, nil) // already have it
return
}
let params = [
"AccessToken" : “xadijdiwjad12121”]
// Can’t use the destination file anymore because my server only return one file name “invoice.pdf” no matter which file i gonna download
// So I have to manually edit my file name which i saved after it was downloaded.
let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)
// So I have to save file name like that ““2016_04_02_car_invoice_10021.pdf” [Date_car_invoice_timestamp(Long).pdf]
// Please look comment on tableView code
Alamofire.Manager.sharedInstance.session.configuration.HTTPAdditionalHeaders?.updateValue("application/pdf",forKey: "Content-Type")
Alamofire.download(.POST, invoice.url,parameters:params, destination: destination)
.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
print(totalBytesRead)
dispatch_async(dispatch_get_main_queue()) {
let progress = Double(totalBytesRead) / Double(totalBytesExpectedToRead)
completionHandler(progress, nil)
}
}
.responseString { response in
print(response.result.error)
completionHandler(nil, response.result.error)
}
}
Here is the table view which gonna check downloaded file and when it click,shown on open in feature.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let invoice = dataController.invoices?[indexPath.row] {
dataController.downloadInvoice(invoice) { progress, error in
// TODO: handle error
print(progress)
print(error)
if (progress < 1.0) {
if let cell = self.tableView.cellForRowAtIndexPath(indexPath), invoiceCell = cell as? InvoiceCell, progressValue = progress {
invoiceCell.progressBar.hidden = false
invoiceCell.progressBar.progress = Float(progressValue)
invoiceCell.setNeedsDisplay()
}
}
if (progress == 1.0) {
// Here where i gonna get the downloaded file name from my model.
// invoice.filename = (Assume “2016_04_02_car_invoice_10021”)
if let filename = invoice.filename{
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docs = paths[0]
let pathURL = NSURL(fileURLWithPath: docs, isDirectory: true)
let fileURL = NSURL(fileURLWithPath: filename, isDirectory: false, relativeToURL: pathURL)
self.docController = UIDocumentInteractionController(URL: fileURL)
self.docController?.delegate = self
if let cell = self.tableView.cellForRowAtIndexPath(indexPath) {
self.docController?.presentOptionsMenuFromRect(cell.frame, inView: self.tableView, animated: true)
if let invoiceCell = cell as? InvoiceCell {
invoiceCell.accessoryType = .Checkmark
invoiceCell.setNeedsDisplay()
}
}
}
}
}
}
}
So,my question is simple.I just don't want to use that code
let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)
because it use response.suggestedfilename.And I want to save file name manually on selected table view cell data.Any Help?Please don't mind that I posted some code in my question because I want everyone to see it clearly.
Destination is of type (NSURL, NSHTTPURLResponse) -> NSURL. so you can do something like this
Alamofire.download(.POST, invoice.url,parameters:params, destination: { (url, response) -> NSURL in
let pathComponent = "yourfileName"
let fileManager = NSFileManager.defaultManager()
let directoryURL = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let fileUrl = directoryURL.URLByAppendingPathComponent(pathComponent)
return fileUrl
})
.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
print(totalBytesRead)
dispatch_async(dispatch_get_main_queue()) {
let progress = Double(totalBytesRead) / Double(totalBytesExpectedToRead)
completionHandler(progress, nil)
}
}
.responseString { response in
print(response.result.error)
completionHandler(nil, response.result.error)
}
}
Swift 3.0
in swift 3.0 it's DownloadFileDestination
Alamofire.download(url, method: .get, to: { (url, response) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in
return (filePathURL, [.removePreviousFile, .createIntermediateDirectories])
})
.downloadProgress(queue: utilityQueue) { progress in
print("Download Progress: \(progress.fractionCompleted)")
}
.responseData { response in
if let data = response.result.value {
let image = UIImage(data: data)
}
}
for more go to the Alamofire