Search code examples
iosswiftalamofireuiimagepickercontroller

How to get photo local url from image picker in swift 4


I want upload a photo from gallery (iOS) to server (uploadUrl getting by .getWalluploadUrl in code is correct) by pod Alamofire (SessionManager) I'm trying to get a photo choosing it with a imagePicker. But a have an error next in Alamofire uploading:

multipartEncodingFailed(reason: Alamofire.AFError.MultipartEncodingFailureReason.bodyPartFileNotReachableWithError(atURL: file:///var/mobile/Containers/Data/Application/366A5FD0-D597-44DC-A6C7-943DDEAB03B7/Documents/asset.JPG, error: Error Domain=NSCocoaErrorDomain Code=260 "The file “asset.JPG” couldn’t be opened because there is no such file." UserInfo={NSURL=file:///var/mobile/Containers/Data/Application/366A5FD0-D597-44DC-A6C7-943DDEAB03B7/Documents/asset.JPG, NSFilePath=/var/mobile/Containers/Data/Application/366A5FD0-D597-44DC-A6C7-943DDEAB03B7/Documents/asset.JPG, NSUnderlyingError=0x28375c9f0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}))

Why does this file not exist? Where did I get the wrong local path with a imagePicker?

Code (I know this code is very bad, but I just wanted to figure out the problem with local path):

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    let imageUrl          = info[UIImagePickerController.InfoKey.referenceURL] as! NSURL
    let imageName         = imageUrl.lastPathComponent
    let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
    let photoURL          = NSURL(fileURLWithPath: documentDirectory)
    let localPath         = photoURL.appendingPathComponent(imageName!)
    let image             = info[UIImagePickerController.InfoKey.originalImage]as! UIImage
    let data              = image.pngData()

    self.getWalluploadUrl { (uploadUrl) in
        let sessionManager = SessionManager.default
        sessionManager.upload(
            multipartFormData: {
                data in
                data.append(
                    localPath!, //????? Incorrect path
                    withName: "file",
                    fileName: imageName!,
                    mimeType: "image/jpeg"
                )
        },
            to: uploadUrl,
            encodingCompletion: {
                (encodingResult) in
                switch encodingResult {
                case .success(let upload, _, _):
                    upload
                        .uploadProgress { (progress) in
                            print("progress:",progress)
                        }
                        .responseJSON { response in
                            switch response.result {
                            case .success(let value):
                                let json = JSON(value)
                                print(json)
                            case .failure(let error):
                                print(error)
                            }

                    }
                case .failure(let error):
                    print(error)
                }
        }
        )

    }

Solution

  • I found the right way for Swift 4.2. It works:

    let photoLocalUrl = (info[UIImagePickerController.InfoKey.imageURL] as? URL)!
    

    It does not need to use .path.lastPathComponent. This is already the full and correct local path (as URL).

    Note: all photos URLs (and for other files) are temporary and the next time you start the application will be different.