2015-09-03 34 views
5

Problemy z przesyłaniem obrazów na mój serwer z rozwijanej aplikacji na iOS. Używam Alamofire i UIImagePickerController.Błąd Alamofire Kod = -1000 "Adres URL nie wskazuje adresu URL pliku"

Wewnątrz metody delegatazapisuję plik, który użytkownik wybiera jako NSURL z info[UIImagePickerControllerReferenceURL] w zmiennej o nazwie self.imageNSURL.

Passing to razem do Alamofires przesłać metodę multipartFormData jako takie (dość dużo standardowy kopiowania i wklejania ich 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) 
     } 
    } 
) 

Błąd w zamian otrzymuję jest

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} 

Uwaga , Nosiłem identyfikator w odpowiedzi na ten post, aktualny komunikat o błędzie zawiera prawidłowe.

Odpowiedz

3

Cóż, jest to spowodowane adresem URL zwrócony z info[UIImagePickerControllerReferenceURL] ten adres URL wskazuje na zasoby-biblioteka/zasób, ze względu na piaskownicę. Nie możesz uzyskać dostępu do pliku przy użyciu tego adresu URL, dlatego alamofire skarży się, że Twój URL nie jest adresem URL pliku. Aby rozwiązać ten problem, możesz użyć multipartFormData.appendBodyPart(data: data, name: name). Ta metoda pobiera dane do wysłania bezpośrednio pod numer NSData. Pełny przykład kodu:

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

Witam! Czy istnieje sposób na uzyskanie prawidłowej ścieżki? Jawnie poprawna ścieżka do pliku w Katalogu dokumentów? –

0

Wpadłem na ten sam problem wcześniej. Na szczęście Alamofire ma sposób obejścia konieczności jawnego przesłania pliku .jpeg na serwer, co jest korzystne, ponieważ pozwala uniknąć czasu potrzebnego na zapisanie obrazu na dysku na dysku NSData. Osiąga się to za pomocą multipartFormData.appendBodyPart(data: imageData, name: "image", fileName: "image.jpeg", mimeType: "image/jpeg").

Poniżej znajduje się bardziej szczegółowy przykład:

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

miałem taki sam problem z lokalną ścieżkę obrazu & które rozwiązany przez ustawienie właściwej ścieżce

funkcji użytkowych

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

Złóż wniosek

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 

      } 
     } 
    ) 
}