I was wondering, if there is a different and faster solution to the following problem. I am downloading a file with NSURLSession. By default (I guess?) the downloaded file is stored in the tmp folder. Then I need to copy this file to the cache folder. At the moment I am using this code for my approach (in the didFinishDownloading function)
if let fileData = NSData(contentsOfURL: sourceUrl) {
fileData.writeToURL(destinationURL, atomically: true) // true
print(destinationURL.path!)
}
However, as my file is pretty large, this takes a while.
Is there a different option on copying this file to the cache folder?
Or is it possible to download a file directly to the Cache folder using the NSURLSession?
Instead of copying the file you can simply move it to the
desired location:
do {
try NSFileManager.defaultManager().moveItemAtURL(sourceURL, toURL: destinationURL)
} catch let err as NSError {
print(err.localizedDescription)
}
This would be much faster because only directory entries in the
file system are modified, but no data is actually copied.
Swift 3 update:
do {
try FileManager.default.moveItem(at: sourceURL, to: destinationURL)
} catch {
print(error.localizedDescription)
}
Related
I have a method that copies images and videos the user selected from the iOS photo library to a temporary cache folder (under the app's Documents directory) but image files that are JPEG or TIFF have their creation and modified dates changed to current date when using FileManager.default.copyItem. I noticed this issue only occurs for some image types and for some others (GIF, PNG, ...) the original creation and modified date is retained.
Here's the method I'm using for it. I'm aware copyItem isn't the most optimal to use (non-atomic). Does anyone know a better way to copy files while retaining dates of all supported file types?
public func copyFileToUploadCache(fileURL: URL) -> URL?
{
guard let uploadCacheFolderURL = uploadCacheFolderURL else { return nil }
let temporaryFileURL = uploadCacheFolderURL.appendingPathComponent(fileURL.lastPathComponent)
var result: URL? = nil
do
{
try FileManager.default.copyItem(at: fileURL, to: temporaryFileURL)
result = temporaryFileURL
}
catch
{
print("Error copying file to upload cache: \(error.localizedDescription).")
}
return result
}
I'm basically trying to save an audio file to an iPhone device, specifically in the Files app.
This is the code I'm using which works in the iOS Simulator:
if let audioUrl = URL(string: "https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3") {
// then lets create your document folder url
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// lets create your destination file url
let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
print(destinationUrl)
// to check if it exists before downloading it
if FileManager.default.fileExists(atPath: destinationUrl.path) {
print("The file already exists at path", destinationUrl)
// if the file doesn't exist
} else {
// you can use NSURLSession.sharedSession to download the data asynchronously
URLSession.shared.downloadTask(with: audioUrl) { location, response, error in
guard let location = location, error == nil else { return }
do {
// after downloading your file you need to move it to your destination url
try FileManager.default.moveItem(at: location, to: destinationUrl)
print("File moved to documents folder", destinationUrl)
} catch {
print(error)
}
}.resume()
}
}
this is the result in the simulator:
2022-04-08 15:48:17.605964+0200 TunnelPlay[3977:122650] [boringssl] boringssl_metrics_log_metric_block_invoke(153) Failed to log metrics
File moved to documents folder file:///Users/panashemuzamhindo/Library/Developer/CoreSimulator/Devices/A7F7DD88-1E0C-45CD-9783-F46E6644F98C/data/Containers/Data/Application/EDE8B3CC-C290-4369-8B88-4AE1717B9DB8/Documents/1645329769Sengkhathele(featit.caramel).mp3
Main Problem: When I try run this section in TestFlight, the app runs the save process but theres nothing in Files, maybe I'm looking for it in the wrong location? or I need some permissions?
Desired Outcome: I want to see the downloaded MP3 in the iPhone Files app.
And I did try to change the scheme to Release instead of Debug, but it still doesn't save the file.
If you want to be able to access the files in the iOS Files app, make sure to also enable LSSupportsOpeningDocumentsInPlace (in addition to enabling UIFileSharingEnabled)
LSSupportsOpeningDocumentsInPlace
A Boolean value indicating whether the app may open the original document from a file provider, rather than a copy of the document.
UIFileSharingEnabled
A Boolean value indicating whether the app shares files.
I have a WKWebView app which i will like to clear a specific cache when image is uploaded .
When i upload an image, the name remains same but the old image will be override with new one, like old image is logo.png, new image will be renamed with logo.png also. But because of cache users will still be seeing the old image.
I have below line of code to clear cache once image has been uploaded and it working fine, but my only problem now is that all cached data is being cleared also.
Is there any way i can clear cache for just the image was uploaded, maybe by passing the image name?
Or just clear cache for images?
static func clearCache(){
let cacheURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
let fileManager = FileManager.default
do {
// Get the directory contents urls (including subfolders urls)
let directoryContents = try FileManager.default.contentsOfDirectory( at: cacheURL, includingPropertiesForKeys: nil, options: [])
for file in directoryContents {
print("CACHE = ", file)
do {
try fileManager.removeItem(at: file)
}
catch let error as NSError {
debugPrint("Ooops! Something went wrong: \(error)")
}
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
From the loop i got this
CACHE =
file:///private/var/mobile/Containers/Data/Application/BFEB788B-9EA4-4921-A902-230869CAC814/Library/Caches/com.myapp.ios.sellers/
CACHE =
file:///private/var/mobile/Containers/Data/Application/BFEB788B-9EA4-4921-A902-230869CAC814/Library/Caches/google-sdks-events/
CACHE =
file:///private/var/mobile/Containers/Data/Application/BFEB788B-9EA4-4921-A902-230869CAC814/Library/Caches/com.apple.WebKit.WebContent/
CACHE =
file:///private/var/mobile/Containers/Data/Application/BFEB788B-9EA4-4921-A902-230869CAC814/Library/Caches/WebKit/
It seems like you need to find the file you want to remove when you are in the for loop loop for files. Remove that specific image when the for loop hits. Right now that for loop removes all cache in directoryContents.
hope you are doing good in development. I have a question regarding Zipping currently i am using Zip framework which I am using for zip the all captured image in device but the problem here is I do not want to save the Zip file in document directory instead I wanna save this memory itself. I am struggling since last week please let me know how can we achieve the zipping without saving it in local directory filepath
Also when I captured the image successfully I saved it to local directory using
let documentsDirectory = FileManager.default.urls(for:
.documentDirectory, in: .userDomainMask).first!
let fileName = "image.jpg"
let fileURL = documentsDirectory.appendingPathComponent(fileName)
if let data = UIImageJPEGRepresentation(image, 1.0),
!FileManager.default.fileExists(atPath: fileURL.path) {
do {
// writes the image data to disk
try data.write(to: fileURL)
print("file saved")
} catch {
print("error saving file:", error)
}
}
After when I am trying to send the image before our server I want to make it all one file so I have implemented the Zip (framework)
Here filpathArray meant all captured image in local path
do {
var urls = [URL]()
for i in 0..<(self.filePathArray.count)
{
urls.append(self.filePathArray[i] as! URL)
}
if self.filePathArray.count > 0 {
let zipFiles = try Zip.quickZipFiles(urls, fileName: "AllFiles")
}
}
Here zipping is done successfully but it saved in local path so when using app container I can able to see the images, I do not want to see the images in device like apple sandbox or Xcode container itself
I want to make zipping on the flow like without saving it document directory, Thanks in advance.
I want to create pre-seed database at the beginning
The file is quite large (5mb).
I use copyItemAtPath to copy files, so do this method has completion?
How do i know when this process has been finished?
This code is enough:
do {
// copy files from main bundle to documents directory
print("copy")
try
NSFileManager.defaultManager().copyItemAtPath(sourcePath, toPath: destinationPath)
} catch let error as NSError {
// Catch fires here, with an NSError being thrown
print("error occurred, here are the details:\n \(error)")
}
where destinationPath can be for example:
NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, .UserDomainMask, true).first
From How to show the progress of copying a large file in iOS?
Run your copying process in a seperate thread (T1)
Run another thread (T2) which reads periodically (say every 100ms)
the destination file current_size.
Calculate the percentage to display progress: current_size / total_size