2015-09-03 20 views
5

Problemi di caricamento di immagini sul mio server dall'applicazione iOS che sto sviluppando. Sto usando Alamofire e uno UIImagePickerController.Alamofire error Code = -1000 "L'URL non punta a un URL di file"

All'interno del metodo delegato didFinishPickingMediaWithInfo sto salvando il file selezionato dall'utente come NSURL da info[UIImagePickerControllerReferenceURL] in una variabile denominata self.imageNSURL.

Passando questo insieme a Alamofires caricare metodo multipartFormData in quanto tale (praticamente una copia standard e incolla dal loro 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) 
     } 
    } 
) 

L'errore in cambio che sto ottenendo è

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} 

Si prega di notare , Ho cancellato gli ID nella risposta per questo post, il messaggio di errore reale contiene quelli validi.

risposta

3

Bene, questo è dovuto all'URL restituito da info[UIImagePickerControllerReferenceURL] questo URL punta a beni-libreria/risorsa, questo a causa del sandboxing. Quindi non puoi accedere al file usando questo URL ecco perché alamofire si lamenta che il tuo URL non sia un URL di file. Per risolvere questo problema è possibile utilizzare multipartFormData.appendBodyPart(data: data, name: name) in questo modo i dati devono essere inviati direttamente come NSData. Esempio di codice completo:

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

Hi! C'è un modo per ottenere il percorso corretto? Percorso esplicitamente corretto per il file in Document Directory? –

0

Mi sono imbattuto in questo stesso problema prima. Fortunatamente Alamofire ha un modo per caricare esplicitamente un file .jpeg sul tuo server, il che è utile poiché evita il tempo necessario per scrivere l'immagine NSData su disco. Questo è realizzato con multipartFormData.appendBodyPart(data: imageData, name: "image", fileName: "image.jpeg", mimeType: "image/jpeg").

Di seguito è riportato un esempio più dettagliato:

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

ho avuto lo stesso problema con il locale percorso dell'immagine & che ha risolto impostando percorso corretto

Funzioni di utilità

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!") 
    } 
} 

fa la richiesta di

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 

      } 
     } 
    ) 
}