I want to save images to documents/images/AET/1.jpg but so far I was able to save to documents folder only.
I wrote code
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("images")
try! fileManager.createDirectory(atPath: paths, withIntermediateDirectories: true, attributes: nil)
fileManager.changeCurrentDirectoryPath(paths)
let image = imagePic// UIImage(named: "apple.jpg")
print(paths)
let paths3 = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("/\(chkString!).jpg")
print("chkString=\(chkString!)")
if !fileManager.fileExists(atPath: paths){
try! fileManager.createDirectory(atPath: paths3, withIntermediateDirectories: true, attributes: nil)
}else{
print("Already dictionary created.")
}
let imageData = UIImageJPEGRepresentation(image, 0.5)
// let pathToDatabase = paths3.appending("/\(chkString)")
// let pathToDatabase = paths3.appendingPathComponent("/\(chkString)")
fileManager.createFile(atPath: paths3 as String, contents: imageData, attributes: nil)
print("imagePath = \(paths3)")
The main issue is that you cannot create a directory passing a file path including the file name (/../AET/1.jpg). You need to specify a folder path without the file name.
Generally it's highly recommended to use the URL related API.
This example uses the URL related API, more descriptive variable names and the API of Data to write the image data to disk.
let chkString : String? = "AET"
let fileManager = FileManager.default
do {
let documentDirectoryURL = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let imagesFolderURL = documentDirectoryURL.appendingPathComponent("images/\(chkString!)")
let imageURL = imagesFolderURL.appendingPathComponent("1.jpg")
let image = imagePic// UIImage(named: "apple.jpg")
if !fileManager.fileExists(atPath: imagesFolderURL.path){
try fileManager.createDirectory(at: imagesFolderURL, withIntermediateDirectories: true, attributes: nil)
} else {
print("Already dictionary created.")
}
let imageData = UIImageJPEGRepresentation(image, 0.5)
try imageData!.write(to: imageURL)
print("imagePath =", imageURL.path)
} catch {
print(error)
}
let fileManager = FileManager.default
let documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let path = "\(documentPath[0])/images/AET"
if !fileManager.fileExists(atPath: path) {
try! fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
} else {
print("Directroy is already created")
}
You can print the path and check through terminal it will give the directory that you want.
Use this:
let fileManager = FileManager.default
let documentPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
print(documentPath)
let imageFolder = documentPath.appending("/images/AET")
if !fileManager.fileExists(atPath: imageFolder) {
do{
try fileManager.createDirectory(atPath: imageFolder, withIntermediateDirectories: true, attributes: nil)
}
catch (let error){
print("Failed to create Directory: \(error.localizedDescription)")
}
}
You should create subfolders like "/images/AET".
Related
Code:
let folderName = "coinFolder"
let fileManager = FileManager.default
let documentsFolder = try! fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let folderURL = documentsFolder.appendingPathComponent(folderName)
let folderExists = (try? folderURL.checkResourceIsReachable()) ?? false
do {
if !folderExists {
try! fileManager.createDirectory(at: folderURL, withIntermediateDirectories: false)
}
let destinationFileUrl = folderURL.appendingPathComponent("test23.pdf")
// let hello = Data("hello".utf8)
// try hello.write(to: fileURL)
let urlString = ""
let url = URL(string: urlString)
let fileName = String((url!.lastPathComponent)) as NSString
// Create destination URL
/* let documentsUrl:URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
let destinationFileUrl = documentsUrl.appendingPathComponent("\(fileName)")*/
//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 {
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
}
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
do {
//Show UIActivityViewController to save the downloaded file
let contents = try FileManager.default.contentsOfDirectory(at: documentsFolder, 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()
}
i am working on sample a project to download PDF file and create folder inside files app and store pdf file inside it.above code is what tried to achieve same.but it is not working for me.is it possible do so?if so what is wrong with my code. any help will be appricated.thanks in advance
I assume you need to change from create:false to create:true
Change from
let documentsFolder = try! fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
To
let documentsFolder = try! fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
When recording videos I create a custom folder using "/MyFolder" like this:
guard let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else { return }
let dirPath = "\(documentsPath)/MyFolder/Videos_\(UUID().uuidString).mp4"
let outputFileURL = URL(fileURLWithPath: dirPath)
// ...
Now I have a function to delete just custom folders:
func deleteCustom(folder: String) {
let fileManager = FileManager.default
guard let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let customFolder = documentsDirectory.appendingPathComponent(folder)
guard let filePaths = try? fileManager.contentsOfDirectory(at: customFolder, includingPropertiesForKeys: nil, options: []) else { return }
for filePath in filePaths {
try? fileManager.removeItem(at: filePath)
}
}
In the function parameter should I pass in "MyFolder" or "/MyFolder"?
In the function parameter should I pass in "MyFolder" or "/MyFolder"?
"MyFolder", because appendingPathComponent adds / automatically.
I am creating new folder using createDirectory with below code.
*let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
// Get documents folder
let documentsDirectory: String = paths.first ?? ""
// Get your folder path
let dataPath = documentsDirectory + "/MyNewFolder"
print("Path\(dataPath)")
if !FileManager.default.fileExists(atPath: dataPath) {
// Creates that folder if no exists
try? FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil)
}*
Now i want to store new file like log.text under “MyNewFolder”. Can anybody suggest me how to save new files under “MyNewFolder” folder
Thanks in advance.
NSSearchPathForDirectoriesInDomains is outdated. The recommended API is the URL related API of FileManager
let folderName = "MyNewFolder"
let fileManager = FileManager.default
let documentsFolder = try! fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let folderURL = documentsFolder.appendingPathComponent(folderName)
let folderExists = (try? folderURL.checkResourceIsReachable()) ?? false
do {
if !folderExists {
try fileManager.createDirectory(at: folderURL, withIntermediateDirectories: false)
}
let fileURL = folderURL.appendingPathComponent("log.txt")
let hello = Data("hello".utf8)
try hello.write(to: fileURL)
} catch { print(error) }
You are strongly discouraged from building paths by concatenating strings.
You can try
try? FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: false, attributes: nil)
do {
let sto = URL(fileURLWithPath: dataPath + "log.txt") // or let sto = URL(fileURLWithPath: dataPath + "/log.txt")
try Data("SomeValue".utf8).write(to: sto)
let read = try Data(contentsOf: sto)
print(String(data: read, encoding: .utf8)!)
}
catch {
print(error)
}
let filePath = dataPath + "/log.txt"
FileManager.default.createFile(filePath, contents:dataWithFileContents, attributes:nil)
I've read some answers for similar questions and every time the problem was in saving absolute path instead of saving just file name and recreating url every time. I've tried to follow examples of code that I saw in these answers, but result was the same : "Could not read from file because there is no such file or directory". I messed up somewhere for sure, and some help would be appreciated
Writing:
let dir = FileManager.default
.urls(for: .documentDirectory, in: .userDomainMask)[0]
let accountDir = dir.appendingPathComponent("\(self.getHexString(str: self.account))", isDirectory: true)
let imageUrl = accountDir.appendingPathComponent("\(self.path.rawValue)")
if let imageData = UIImagePNGRepresentation(image) {
FileManager().createFile(atPath: imageUrl.path, contents: imageData, attributes: nil)
}
Reading:
let dir = FileManager.default
.urls(for: .documentDirectory, in: .userDomainMask)[0]
let accountDir = dir.appendingPathComponent("\(self.getHexString(str: self.account))", isDirectory: true)
let imageUrl = accountDir.appendingPathComponent("\(self.path.rawValue)")
let imageData = try Data(contentsOf: imageUrl)
There can be two reasons:
It is not creating the path properly.
Try changing image.path to image.absoluteString
I think it is just creating the file but not writing anything in that
Try the below code after createfile:
let file = try FileHandle(forUpdating: imageUrl)
file.seekToEndOfFile()
file.write(data: imageData)
file.closeFile()
I thought that directory where I wanted to store my images is created automatically when I append it to path and flag isDirectory: true, but it doesn't. So the correct code is :
let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let accountDir = dir.appendingPathComponent("\(self.getHexString(str: self.account))", isDirectory: true)
let isDirectoryExists = FileManager.default.fileExists(atPath: accountDir.path)
if !isDirectoryExists {
do {
try FileManager.default.createDirectory(atPath: accountDir.path, withIntermediateDirectories: false, attributes: nil)
} catch(let error) {
print(error)
}
}
let imageUrl = accountDir.appendingPathComponent("\(self.path.rawValue)")
if let imageData = UIImagePNGRepresentation(image) {
FileManager().createFile(atPath: imageUrl.path, contents: imageData, attributes: nil)
}
// directoryPath is a URL from another VC
#IBAction func saveButtonTapped(sender: AnyObject) {
let directoryPath = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL
let urlString : NSURL = directoryPath.URLByAppendingPathComponent("Image1.png")
print("Image path : \(urlString)")
if !NSFileManager.defaultManager().fileExistsAtPath(directoryPath.absoluteString) {
UIImageJPEGRepresentation(self.image, 1.0)!.writeToFile(urlString.absoluteString, atomically: true)
displayImageAdded.text = "Image Added Successfully"
} else {
displayImageAdded.text = "Image Not Added"
print("image \(image))")
}
}
I am not getting any error but the Image is not getting saved in the document.
The problem there is that you are checking if the folder not exists but you should check if the file exists. Another issue in your code is that you need to use url.path instead of url.absoluteString. You are also saving a jpeg image using a "png" file extension. You should use "jpg".
edit/update:
Swift 4.2 or later
do {
// get the documents directory url
let documentsDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
print("documentsDirectory:", documentsDirectory.path)
// choose a name for your image
let fileName = "image.jpg"
// create the destination file url to save your image
let fileURL = documentsDirectory.appendingPathComponent(fileName)
// get your UIImage jpeg data representation and check if the destination file url already exists
if let data = image.jpegData(compressionQuality: 1),
!FileManager.default.fileExists(atPath: fileURL.path) {
// writes the image data to disk
try data.write(to: fileURL)
print("file saved")
}
} catch {
print("error:", error)
}
To write the image at the destination regardless if the image already exists or not you can use .atomic options, if you would like to avoid overwriting an existing image you can use withoutOverwriting instead:
try data.write(to: fileURL, options: [.atomic])
This is my answer for Swift 3, combining the 2 answers above:
let documentsDirectoryURL = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
// create a name for your image
let fileURL = documentsDirectoryURL.appendingPathComponent("Savedframe.png")
if !FileManager.default.fileExists(atPath: fileURL.path) {
do {
try UIImagePNGRepresentation(imageView.image!)!.write(to: fileURL)
print("Image Added Successfully")
} catch {
print(error)
}
} else {
print("Image Not Added")
}
An extension method in swift 4.2
import Foundation
import UIKit
extension UIImage {
func saveToDocuments(filename:String) {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsDirectory.appendingPathComponent(filename)
if let data = self.jpegData(compressionQuality: 1.0) {
do {
try data.write(to: fileURL)
} catch {
print("error saving file to documents:", error)
}
}
}
}
#IBAction func saveButtonTapped(sender: AnyObject) {
let directoryPath = try! NSFileManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
let urlString : NSURL = directoryPath.URLByAppendingPathComponent("Image1.png")
print("Image path : \(urlString)")
if !NSFileManager.defaultManager().fileExistsAtPath(urlString.path!) {
UIImageJPEGRepresentation(self.image, 1.0)!.writeToFile(urlString.path! , atomically: true)
displayImageAdded.text = "Image Added Successfully"
} else {
displayImageAdded.text = "Image Not Added"
print("image \(image))")
}
}
Put the image in an NSData object; writing to a file with this class is a breeze, and it'll make the file size smaller.
By the way, I recommend NSPurgeableData. After saving the image, you can mark the object as purgeable, which will keep memory consumption. That may be a problem with your app, but might be with another you're crowding out.
In Swift 4.2 and Xcode 10.1
func saveImageInDocsDir() {
let image: UIImage? = yourImage//Here set your image
if !(image == nil) {
// get the documents directory url
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0] // Get documents folder
let dataPath = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("ImagesFolder").absoluteString //Set folder name
print(dataPath)
//Check is folder available or not, if not create
if !FileManager.default.fileExists(atPath: dataPath) {
try? FileManager.default.createDirectory(atPath: dataPath, withIntermediateDirectories: true, attributes: nil) //Create folder if not
}
// create the destination file url to save your image
let fileURL = URL(fileURLWithPath:dataPath).appendingPathComponent("imageName.jpg")//Your image name
print(fileURL)
// get your UIImage jpeg data representation
let data = UIImageJPEGRepresentation(image!, 1.0)//Set image quality here
do {
// writes the image data to disk
try data?.write(to: fileURL, options: .atomic)
} catch {
print("error:", error)
}
}
}
Although the answers are correct, I want to share utility functions for this purpose. You can use the following 2 methods to save and Image in Documents Directory and then load an image from Documents Directory. Here you can find the Detailed Article.
public static func saveImageInDocumentDirectory(image: UIImage, fileName: String) -> URL? {
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!;
let fileURL = documentsUrl.appendingPathComponent(fileName)
if let imageData = UIImagePNGRepresentation(image) {
try? imageData.write(to: fileURL, options: .atomic)
return fileURL
}
return nil
}
public static func loadImageFromDocumentDirectory(fileName: String) -> UIImage? {
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!;
let fileURL = documentsUrl.appendingPathComponent(fileName)
do {
let imageData = try Data(contentsOf: fileURL)
return UIImage(data: imageData)
} catch {}
return nil
}
Answer for Swift 5.x
func saveImageToDocumentsDirectory() {
let directoryPath = try! FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let urlString : NSURL = directoryPath.appendingPathComponent("Image1.png") as NSURL
print("Image path : \(urlString)")
if !FileManager.default.fileExists(atPath: urlString.path!) {
do {
try self.image.jpegData(compressionQuality: 1.0)!.write(to: urlString as URL)
print ("Image Added Successfully")
} catch {
print ("Image Not added")
}
}
}
Note : image = your declared image.