0
votes

I am trying to save and load images to and from the file directory, however my writeImageToPath function prints the following error to the console and says the file does not exist.

Console

Write image to directory

File exists Write image

Error Write image to directory File does NOT exist -- file:///Users/user/Library/Developer/CoreSimulator/Devices/70EAC77D-9F3C-4AFC-8CCA-A7B9B895BDE6/data/Containers/Data/Application/DDAF2EBD-5DDA-4EA6-95D3-6785B74A0B09/Documents/upload/http://i.annihil.us/u/prod/marvel/i/mg/a/f0/5202887448860 -- is available for use Write image Error Writing Image: Error Domain=NSCocoaErrorDomain Code=4 "The file “5202887448860” doesn’t exist." UserInfo={NSFilePath=/Users/user/Library/Developer/CoreSimulator/Devices/70EAC77D-9F3C-4AFC-8CCA-A7B9B895BDE6/data/Containers/Data/Application/DDAF2EBD-5DDA-4EA6-95D3-6785B74A0B09/Documents/upload/http://i.annihil.us/u/prod/marvel/i/mg/a/f0/5202887448860, NSUnderlyingError=0x600003b04ab0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

Here's my code, I am not sure where I am going wrong

// The images are loaded from the web and displayed in the cell.imageView.image

  if let thumbnail = product["thumbnail"] as? [String: Any],
     let path = thumbnail["path"] as? String,
     let fileExtension = thumbnail["extension"] as? String {

  //Save image to directory
  if image != nil {
     writeImageToPath(path, image: image!)
  }

  }


// Write image to directory
func writeImageToPath(_ path: String, image: UIImage) {
    print("Write image to directory")

    let uploadURL = URL.createFolder(folderName: "upload")!.appendingPathComponent(path)

    if !FileManager.default.fileExists(atPath: uploadURL.path) {
        print("File does NOT exist -- \(uploadURL) -- is available for use")

        let uploadURL = URL.createFolder(folderName: "upload")!.appendingPathComponent(path)

        if let data = UIImageJPEGRepresentation(image, 0.9) {
            do {
                print("Write image")
                try data.write(to: uploadURL)
            }
            catch {
                print("Error Writing Image: \(error)")
            }

        } else {
            print("Image is nil")
        }
    } else {
        print("This file exists -- something is already placed at this location")
    }

}


// load image from directory
func loadImageFromPath(_ path: String) -> UIImage? {

    let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]

    let folderURL = documentsURL.appendingPathComponent("upload")

    let fileURL = folderURL.appendingPathComponent(path)

    if FileManager.default.fileExists(atPath: fileURL.path) {
        //Get Image And upload in server
        print("fileURL.path \(fileURL.path)")

        do{
            let data = try Data.init(contentsOf: fileURL)
            let image = UIImage(data: data)
            return image
        }catch{
            print("error getting image")
        }
    } else {
        print("No image in directory")
    }

    return nil
}


extension URL {
static func createFolder(folderName: String) -> URL? {
    let fileManager = FileManager.default
    // Get document directory for device, this should succeed
    if let documentDirectory = fileManager.urls(for: .documentDirectory,
                                                in: .userDomainMask).first {
        // Construct a URL with desired folder name
        let folderURL = documentDirectory.appendingPathComponent(folderName)
        // If folder URL does not exist, create it
        if !fileManager.fileExists(atPath: folderURL.path) {
            do {
                // Attempt to create folder
                try fileManager.createDirectory(atPath: folderURL.path,
                                                withIntermediateDirectories: true,
                                                attributes: nil)
            } catch {
                // Creation failed. Print error & return nil
                print(error.localizedDescription)
                return nil
            }
        }
        // Folder either exists, or was created. Return URL
        return folderURL
    }
    // Will only be called if document directory not found
    return nil
}
}

How can I correctly save and load images from the directory ?

3
Maybe you didn't actually write it in the path correctly? I would add print statements inside your writeToImagePath do { print("Worked" try data!.write(to: fileURL) } catch { print(error) } impression7vx
You have an empty catch block, are you sure that write(to:) doesn't throw an exception?mag_zbc
@impression7vx Check my updated questionA.Roe
@mag_zbc I have updated my question, fileExists actually returns false and the block is not executed.A.Roe
You misunderstood as I probably wasn't clear. Here is my question -- How do you know for sure your path exists in the image directory when you writeToImagePath? When you test writing an image to a file path, does it print "Worked" or does it print the error?impression7vx

3 Answers

2
votes

Below is how I save images to a folder named "Screenshots". I tried to keep it as clear as I could.

func saveImageToDocumentDirectory(image: UIImage) {
    var objCBool: ObjCBool = true
    let mainPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
    let folderPath = mainPath + "/Screenshots/"

    let isExist = FileManager.default.fileExists(atPath: folderPath, isDirectory: &objCBool)
    if !isExist {
        do {
            try FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: true, attributes: nil)
        } catch {
            print(error)
        }
    }

    let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
    let imageName = "\(fileName).png"
    let imageUrl = documentDirectory.appendingPathComponent("Screenshots/\(imageName)")
    if let data = image.jpegData(compressionQuality: 1.0){
        do {
            try data.write(to: imageUrl)
        } catch {
            print("error saving", error)
        }
    }
}

This is how I load images stored in the folder

 func loadImageFromDocumentDirectory(nameOfImage : String) -> UIImage {
    let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
    let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
    let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
    if let dirPath = paths.first{
        let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent("Screenshots/\(nameOfImage)")
        guard let image = UIImage(contentsOfFile: imageURL.path) else { return  UIImage.init(named: "fulcrumPlaceholder")!}
        return image
    }
    return UIImage.init(named: "imageDefaultPlaceholder")!
}
1
votes
class MyImageClass {
    func writeImageToPath(_ path:String, image:UIImage) {
        let uploadURL = URL.createFolder(folderName: "upload")!.appendingPathComponent(path)

        if !FileManager.default.fileExists(atPath: uploadURL.path) {
            print("File does NOT exist -- \(uploadURL) -- is available for use")
            let data = image.jpegData(compressionQuality: 0.9)
            do {
                print("Write image")
                try data!.write(to: uploadURL)
            }
            catch {
                print("Error Writing Image: \(error)")
            }
        }
        else {
            print("This file exists -- something is already placed at this location")
        }
    }
}

extension URL {
    static func createFolder(folderName: String) -> URL? {
        let fileManager = FileManager.default
        // Get document directory for device, this should succeed
        if let documentDirectory = fileManager.urls(for: .documentDirectory,
                                                in: .userDomainMask).first {
            // Construct a URL with desired folder name
            let folderURL = documentDirectory.appendingPathComponent(folderName)
            // If folder URL does not exist, create it
            if !fileManager.fileExists(atPath: folderURL.path) {
                do {
                    // Attempt to create folder
                    try fileManager.createDirectory(atPath: folderURL.path,
                                                withIntermediateDirectories: true,
                                                attributes: nil)
                } catch {
                    // Creation failed. Print error & return nil
                    print(error.localizedDescription)
                    return nil
                }
            }  
            // Folder either exists, or was created. Return URL
            return folderURL
        }
        // Will only be called if document directory not found
        return nil
    }
}

var saving = MyImageClass()
saving.writeImageToPath("whereIWantToSaveTheImageTo", image: UIImage(named: "myImage"))

Reference Create Directory in Swift 3.0

I didn't test if the imaging worked, however, this does create a folder called "Upload" and you can call it every time. The extension has a method called createFolder that returns a folder for whatever you call and creates it if it is not already there. We can just check for the specified path within the folder, then if it is available, we can write to it. I also only rewrote the writeImageToPath portion.

NOTE:

Tested this in playground...

Results were:

File does NOT exist -- file:///var/folders/vs/nlj__xh93vs0f8wzcgksh_zh0000gn/T/com.apple.dt.Xcode.pg/containers/com.apple.dt.playground.stub.iOS_Simulator.MyPlayground-67A67A07-51FF-4DF4-BE80-02E7FDAFA1CA/Documents/upload/whereIWantToSaveTheImageTo -- is available for use
Write image
0
votes

The path name is wrong to replace this function call with the correct path name

writeImageToPath("http://i.annihil.us/u/prod/marvel/i/mg/b/70/4c0035adc7d3a", image: image)

To

writeImageToPath("4c0035adc7d3a", image: image)