Alamofire错误代码= -1000" URL未指向文件URL"

时间:2015-09-03 02:24:18

标签: ios swift uiimagepickercontroller nsurl alamofire

在我正在开发的iOS应用程序中将图像上传到我的服务器时出现问题。我使用的是Alamofire和UIImagePickerController

didFinishPickingMediaWithInfo委托方法中,我保存用户从名为NSURL的变量info[UIImagePickerControllerReferenceURL]中选择self.imageNSURL的文件。

将此传递给Alamofires就这样上传了multipartFormData方法(几乎是标准的副本并从他们的docs粘贴)

Alamofire.upload(
    .POST,
    URLString: "http://app.staging.acme.com/api/users/\(id)/picture",
    multipartFormData: { multipartFormData in
        multipartFormData.appendBodyPart(fileURL: self.imageNSURL, name: "image")
    },
    encodingCompletion: { encodingResult in
        switch encodingResult {
        case .Success(let upload, _, _):
            upload.responseJSON { request, response, JSON, error in
                println(JSON)
            }
        case .Failure(let encodingError):
            println(encodingError)
        }
    }
)   

我得到的错误是

Error Domain=com.alamofire.error Code=-1000 "The operation couldn’t be completed. The URL does not point to a file URL: assets-library://asset/asset.JPG?id=00000000-0000-0000-0000-000000000000&ext=JPG" UserInfo=0x00000000000 {NSLocalizedFailureReason=The URL does not point to a file URL: assets-library://asset/asset.JPG?id=00000000-0000-0000-0000-000000000000&ext=JPG}

请注意,我在此帖子的回复中已经识别了ID,实际的错误消息包含有效的消息。

3 个答案:

答案 0 :(得分:3)

这是因为从info[UIImagePickerControllerReferenceURL]返回的网址此URL指向资产库/资产,这归功于沙盒。因此,您无法使用此URL访问该文件,这就是为什么alamofire会抱怨您的网址不是文件网址的原因。要解决此问题,您可以使用multipartFormData.appendBodyPart(data: data, name: name)此方法将数据直接发送为NSData。完整代码示例:

let imagePicked = info[UIImagePickerControllerOriginalImage]
let imageExtenstion = info[UIImagePickerControllerReferenceURL]
// imageExtenstion will be "asset.JPG"/"asset.JPEG"/"asset.PNG"
// so we have to remove the asset. part
var imagePickedData : NSData
switch imageExtenstion {
    case "PNG": imagePickedData = UIImagePNGRepresentation(imagePicked)!
   // compressionQuality is a float between 0.0 and 1.0 with 0.0 being most compressed with lower quality and 1.0 least compressed with higher quality
    case "JPG", "JPEG": imagePickedData = UIImageJPEGRepresentation(image, compressionQuality)!
}
Alamofire.upload(.POST, YOUR_URL, multipartFormData: { multipartFormData in 
     multipartFormData.appendBodyPart(data: imagePickedData, name: imageName)
 }, encodingCompletion: { encodingResult in
    switch encodingResult {
    case .Success(let upload, _, _):
        upload.responseJSON { request, response, JSON, error in
            print(JSON)
        }
    case .Failure(let encodingError):
        print(encodingError)
    }
})

答案 1 :(得分:0)

之前我遇到过同样的问题。幸运的是,Alamofire可以将.jpeg文件显式上传到服务器,这是有益的,因为它避免了将映像NSData写入磁盘所需的时间。这是通过multipartFormData.appendBodyPart(data: imageData, name: "image", fileName: "image.jpeg", mimeType: "image/jpeg")完成的。

下面是一个更详细的例子:

Alamofire.upload(.POST, "path/to/resource/to/receive/image/", multipartFormData: { multipartFormData -> Void in
        /**
        - parameter imageData: NSData representation of your image
        - parameter name: String of the name to associated with the data in the Content-Disposition HTTP header. To use an HTML example, "image" in the following code: <input type="file" name="image">
        - parameter fileName: String of the name that you are giving the image file, an example being image.jpeg
        - parameter mimeType: String of the type of file you are uploading (image/jpeg, image/png, etc)
        **/
        multipartFormData.appendBodyPart(data: imageData, name: "image", fileName: "image.jpeg", mimeType: "image/jpeg")
        }, encodingCompletion: { encodingResult in
            switch encodingResult {
            case .Success(let upload, _, _):
                upload.responseJSON { response in
                    debugPrint(response)
                }
            case .Failure(let encodingError):
                print(encodingError)
            }
})

答案 2 :(得分:0)

  

我对本地图像路径有同样的问题&amp;通过设置正确的路径来解决

效用函数

var TimestampJPGImageName :String {
    var stringTimeStamp =  "\(NSDate().timeIntervalSince1970 * 1000)"
    stringTimeStamp = stringTimeStamp.stringByReplacingOccurrencesOfString(".", withString: "_")
    stringTimeStamp = stringTimeStamp.stringByAppendingString(".jpg")
    stringTimeStamp = stringTimeStamp.stringByAddingPercentEncodingWithAllowedCharacters( NSCharacterSet.URLQueryAllowedCharacterSet())!

    return stringTimeStamp
}

func fileUrlForPathComponent(pathComponent: String) -> NSURL?{

    let pathDocumentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
    let filePath = "\(pathDocumentDirectory)/\(pathComponent)"
    let fileUrl = NSURL(fileURLWithPath: filePath)

    return fileUrl
}

func fileSaveToDirectory(image: UIImage, name: String?) -> NSURL? {

    //let fileManager = NSFileManager.defaultManager()
    //fileManager.createFileAtPath(fileUrlToWrite!.path, contents: imageData, attributes: nil)

    var fileUrlToWrite : NSURL? = nil
    if let fileName : String = name {
        fileUrlToWrite = fileUrlForPathComponent(fileName)//.stringByAppendingString(".png")
    }else{
        fileUrlToWrite = fileUrlForPathComponent(TimestampJPGImageName)//.stringByAppendingString(".png")
    }

    assert(fileUrlToWrite != nil, "please check filePath")
    if (fileUrlToWrite != nil){
        let imageData: NSData = UIImageJPEGRepresentation(image, 0.6)!

        imageData.writeToFile(fileUrlToWrite!.path!, atomically: false)

        return fileUrlToWrite!
    }
    else{
        return nil
    }
}

func fileRemoveAtURL(URL : NSURL) ->(success : Bool?, message : String?){

    if let path : String = URL.path{

        let fileManager = NSFileManager.defaultManager()

        do {
            try fileManager.removeItemAtPath(path)
        }
        catch let error as NSError {
            return (false, error.localizedDescription)
        }
        return (true, "file removed!")
    }else{
        return (false, "invalid path!")
    }
}
  

提出请求

func requestCreateEvent(){

    if (canMakeAPIRequest() == false){
        return
    }

    let imageJPEGname = TimestampJPGImageName
    var parameters : Dictionary<String, AnyObject> =
        ["event[eventName]" : configuration.stringEventName,
         "event[images][0][image][imageFile]" : self.imageTaken!,
         "event[images][0][image][imageName]" : imageJPEGname,
    ]
    var headers = [String:String]()
    headers["Content-Type"] = "multipart/form-data"

    let urlpath = URL_CreateEvent.stringByAppendingString("?access_token=\(gblConfiguration!.AppToken!.accessToken)")

    var arrayImageURL : Array<NSURL> = []

    self.view.showLoader()
    Alamofire.upload(.POST, urlpath, headers: headers, multipartFormData: { (multipartFormData) -> Void in

        if let dictUpload : Dictionary<String, AnyObject> = parameters {

            for (key , value) in dictUpload {

                if value.isKindOfClass(UIImage) {

                    if let image = value as? UIImage{

                        /*
                         //Upload Image with Data

                         if let imageData = UIImageJPEGRepresentation(image, 0.8) {
                            multipartFormData.appendBodyPart(data: imageData, name: key, fileName: imageJPEGname, mimeType: "image/jpg")
                        }else if let imageData = UIImagePNGRepresentation(image) {
                            multipartFormData.appendBodyPart(data: imageData, name: key, fileName: "myImage.png", mimeType: "image/png")
                        }*/


                        //Upload Image with URL PATH
                        if let fileURL : NSURL = fileSaveToDirectory(image, name: imageJPEGname)
                        {
                            multipartFormData.appendBodyPart(fileURL: fileURL , name: key)
                            arrayImageURL.append(fileURL)
                        }
                        else {
                            assert(false, "Unable to save file-name \(imageJPEGname)")
                        }
                    }
                }
                else {
                    multipartFormData.appendBodyPart(data: "\(value)".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!, name: key)
                }
            }
        }

        }, encodingMemoryThreshold: Manager.MultipartFormDataEncodingMemoryThreshold, encodingCompletion:{
            encodingResult in

            switch encodingResult {
            case .Success(let request, let _, let _):

                request.responseJSON { response in

                    //debugPrint(response)
                    self.view.hideLoader()

                    if let objResponse : NSHTTPURLResponse = response.response {

                        if objResponse.statusCode == 201 { //SUCCESS STATUS

                            for url : NSURL in arrayImageURL {
                                fileRemoveAtURL(url)
                            }

                            let alert = UIAlertView.init(title: AppName, message: "Event Created!", delegate: nil
                                , cancelButtonTitle: "OK")
                            alert.show()
                            self.navigationController?.popToRootViewControllerAnimated(true)
                        }
                        else if objResponse.statusCode == 500 {
                            let alert = UIAlertView.init(title: AppName, message: "Bad access", delegate: nil
                                , cancelButtonTitle: "OK")
                            alert.show()
                        }
                    }

                    switch response.result {
                    case .Success(let JSON): // Error Handling

                        if let responseDictionary = JSON as? NSDictionary {

                            if let errors = responseDictionary["errors"] {

                                if let _ = errors["errors"] as? Array<String>
                                {
                                    showErrorMessageAlertView(errors, viewdelegate: self)
                                }
                            }
                            else if let error = responseDictionary["error"] as? String,
                                let errorDescription = responseDictionary["error_description"] as? String
                            {
                                let alert = UIAlertView.init(title: error, message: errorDescription, delegate: nil
                                    , cancelButtonTitle: "OK")
                                alert.show()
                            }
                        }
                    case .Failure(let error):
                        print("Request failed with error: \(error)")
                    }
                }
                break

            case .Failure(let encodingError as NSError):
                print(encodingError)
                self.view.hideLoader()

                showErrorMessageAlertView(encodingError, viewdelegate: nil)
                break

            default :
                self.view.hideLoader()
                break

            }
        }
    )
}