Upload files to a server from IOS app with swift

1

I'm making an app with which you can upload images to a server (It's in PHP 5.2 ).

Firstly, to upload the image, I did it at the moment when the button was clicked to go up from the app and it showed a alertview with a load bar, but it took too long.

Currently I have changed it so that when you click the upload button from the app, the body of the request http , is saved in the database and then when you navigate to view controller it is activated the upload from background asynchronously, so the user does not waste time.

The problem is that when I save in the database and then read it again, the request POST does not work correctly and does not send me the body of the request

Do not know if this is the best way to do it or there are other better and more efficient ones.

Here is an example of my code if it is correct:

//Aqui genero el body de la peticion
func createBodyWithParameters(parameters: String?, filePathKey: String, imageDataKey: NSData, boundary: String, nameParam: String) -> NSData {
    let body = NSMutableData()
    let mimetype = "image/jpg"
    let nombreImagen = obtenerNombreImagen()

    body.appendString("--\(boundary)\r\n")
    body.appendString("Content-Disposition:form-data; name=\"\(nameParam)\"\r\n\r\n")
    body.appendString("\(cadenaParametros)\r\n")

    body.appendString("--\(boundary)\r\n")
    body.appendString("Content-Disposition:form-data; name=\"\(filePathKey)\"; filename=\"\(nombreImagen)\"\r\n")
    body.appendString("Content-Type: \(mimetype)\r\n\r\n")
    body.appendData(imageDataKey)
    body.appendString("\r\n")

    body.appendString("--\(boundary)--\r\n")

    return body
}

func subirImagen() {
    if (myImageView.image != nil) {
        let boundary = generateBoundaryString()
        let imageData = UIImageJPEGRepresentation(myImageView.image!, 1)

        if(imageData == nil) {
            return
        }

        let body: NSData = self.createBodyWithParameters(paramString, filePathKey: "imagen", imageDataKey: imageData!, boundary: boundary, nameParam: "param_img")
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
            GestorDB.uploadFiles("Imagen", ruta: stringUrl, parametros: paramString, body: body, tipoPeticion: "POST", respuesta: "", estado: 0)

            dispatch_async(dispatch_get_main_queue(),{
                progressAlert.dismissWithClickedButtonIndex(-1, animated: true)
                let alertController = UIAlertController(title: "", message:
                    "Imagen añadida correctamente", preferredStyle: UIAlertControllerStyle.Alert)
                alertController.addAction(UIAlertAction(title: "Aceptar", style: UIAlertActionStyle.Default, handler: { (action: UIAlertAction!) in
                    self.performSegueWithIdentifier("volver", sender: self)
                }))
                self.presentViewController(alertController, animated: true, completion: nil)
            })
        }
    }
}

/*Clase gestorDb*/
//El campo de la tabla donde se guarda el body es tipo TEXT
class func uploadFiles(nombre: String, ruta: String, parametros: String, body: NSData, tipoPeticion: String, respuesta: String, estado: Int) -> Bool {
    let ubicacionDB = self.obtenerRutaDB()
    let database = FMDatabase(path: ubicacionDB as String)
    if !database.open() {
        return false
    }
    else {
        let sentenciaSql = "INSERT INTO archivo(nombre_archivo, ruta_archivo, parametros, body, tipo_peticion, respuesta, estado) VALUES(?, ?, ?, ?, ?, ?, ?)"
        if !database.executeUpdate(sentenciaSql, withArgumentsInArray: [nombre, ruta, parametros, body, tipoPeticion, respuesta, estado]) {
            database.close()
            return false
        }
        else {
            //print("INSERT CORRECT")
            return true
        }
    }
}
//Obtengo los datos
class func getFilesToUpload() -> FMResultSet {
    let ubicacionDB = self.obtenerRutaDB()
    let database = FMDatabase(path: ubicacionDB as String)
    if !database.open() {
        //print("No se puede abrir la bbdd")
    }
    let sentenciaSql = "SELECT * FROM archivo WHERE estado = 0"
    let results:FMResultSet? = database.executeQuery(sentenciaSql, withArgumentsInArray: nil)
    return results!
}

/*ViewController*/
//Aqui obtengo losd atos de peticion guardadas no enviadas y las envio
if AppDelegate().isConnectedToNetwork() {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
        if GestorDB.getFilesToUpload().next() == true {
            let resultadoSql = GestorDB.getFilesToUpload()
            while resultadoSql.next() == true {
                let idArchivo: Int = Int(resultadoSql.intForColumn("id_archivo")) // .stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
                let rutaArchivo  = resultadoSql.stringForColumn("ruta_archivo").stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
                let parametros  = resultadoSql.stringForColumn("parametros").stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
                var body  = resultadoSql.dataForColumn("body")//.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())

                if body == nil {
                    body = NSData()
                }

                AppDelegate().uploadFile(body, stringUrl: rutaArchivo, parametros: parametros, idArchivo: idArchivo)
            }
        }
        else {
            //print("NOOO")
        }
    }
}


/*AppDelegate*/
func uploadFile(body: NSData, stringUrl: String, parametros: String, idArchivo: Int) {
    let url:NSURL = NSURL(string: stringUrl)!
    let request = NSMutableURLRequest(URL: url)
    let boundary = self.generateBoundaryString()

    request.HTTPMethod = "POST"
    request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringCacheData
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    request.HTTPBody = body

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
        data, response, error in

        if error != nil {
            print("error=\(error)")
            return
        }
        let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)

        print("*** error = \(error)")
        print("**** data = \(data)")
        print("***** request = \(request)")
        print("****** response = \(response)")
        print("******* response data = \(responseString!)")//Me devuelve vacio

        dispatch_async(dispatch_get_main_queue(),{
            GestorDB.updateEstadoFiles(idArchivo)//Aqui solo cambio el estado a 1
        })
    }
    task.resume()
}
    
asked by 24.08.2016 в 10:51
source

1 answer

0

My recommendation is that by pressing the button you send the order and use the AlamoFire pod ( link ) to manage Asynchronous calls to the server.

As an example of a Post I copied the one found in the description of the pod:

let parameters: Parameters = [
    "foo": [1,2,3],
    "bar": [
        "baz": "qux"
    ]
]
  

Both calls are equivalent   Alamofire.request (" link ", method: .post, parameters: parameters, encoding: JSONEncoding.default)   Alamofire.request (" link ", method: .post, parameters: parameters, encoding: JSONEncoding (options: []))

    
answered by 26.10.2016 в 17:31