2015-09-03 30 views
5

發生問題將圖像從我正在開發的iOS應用程序上傳到我的服務器。我正在使用Alamofire,以及UIImagePickerControllerAlamofire錯誤代碼= -1000「URL不指向文件URL」

didFinishPickingMediaWithInfo委託方法中,我將用戶從info[UIImagePickerControllerReferenceURL]中選擇的NSURL保存在名爲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

那麼這是由於從info[UIImagePickerControllerReferenceURL]返回的URL導致這個URL指向資產庫/資產,這是由於沙箱造成的。所以你不能使用這個URL訪問這個文件,這就是爲什麼alamofire抱怨你的URL不是文件的URL。爲了解決這個問題,你可以使用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) 
    } 
}) 
+0

嗨!有沒有辦法如何獲得正確的路徑?在文檔目錄中顯式更正文件的路徑? –

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) 
      } 
}) 
0

我有相同的本地圖片路徑&問題,它通過設置正確的路徑

效用函數

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 

      } 
     } 
    ) 
}