简体   繁体   中英

Encoding base64 string to image in swift received from mysql

I am receiving a base64 string from mysql (stored as blob) and try to encode it like this:

func loadImage() {
    var request = URLRequest(url: URL(string: URL_IMAGES)!)
    request.httpMethod = "POST"
    let userid = self.defaultValues.integer(forKey: "userid")
    let postString = "userid=\(userid)"
    request.httpBody = postString.data(using: .utf8)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            print("error=\(String(describing: error))")
            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(String(describing: response))")
        }

        let responseString = String(data: data, encoding: .utf8)
        if let encodedImage = responseString,
            let imageData =  NSData(base64Encoded: encodedImage, options: .ignoreUnknownCharacters),
            let image = UIImage(data: imageData as Data) {
            print(image.size)
        }
    }
    task.resume()
}

And the php file looks like this:

<?php
$userid=$_POST["userid"];
$conn = mysqli_connect(connection);
if ($conn->connect_error) {
    die("Connection failed: " . $conn>connect_error);
} 
$sql = "SELECT profilepicture FROM users WHERE id = $userid";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
     while($row = $result->fetch_assoc()) {
         $out[]=$row;
     }
    echo json_encode($out);
} else {
  echo "0 results";
}
?>

EDIT 2* And this is how Im storing the image into the database:

@objc func updateUser(sender: UIButton!) {
    let refreshAlert = UIAlertController(title: "Update profile?", message: "Do you want to update your profile? This will log you out to update the data!", preferredStyle: UIAlertControllerStyle.alert)
    refreshAlert.view.tintColor = UIColor.red
    refreshAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action: UIAlertAction!) in

        let URL_REQUEST = "request"

        self.messageLbl.text = ""

        var request = URLRequest(url: URL(string: URL_REQUEST)!)
        request.httpMethod = "POST"
        let userid = self.defaultValues.integer(forKey: "userid")
        let password = self.passWordTf.text!
        let email = self.eMailTf.text!
        let image = self.imageView.image!
        guard let pictStr = self.convertImageBase64(image: image) else {
            return
        }
        let postString = "id=\(userid)&password=\(password)&email=\(email)&profilepicture=\(pictStr)"
        request.httpBody = postString.data(using: .utf8)
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                print("error=\(String(describing: error))")
                return
            }

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
            }

            let responseString = String(data: data, encoding: .utf8)
            print("responseString = \(String(describing: responseString))")
        }
        task.resume()

        if (self.eMailTf.text != self.defaultValues.string(forKey: "useremail")) {
            self.defaultValues.set(self.eMailTf.text, forKey: "useremail")
        }
        self.navigationController?.popViewController(animated: true)
    }))

    refreshAlert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action: UIAlertAction!) in
        print("Handle Cancel Logic here")
    }))

    present(refreshAlert, animated: true, completion: nil)
}

EDIT 2* This is the encoding function:

func convertImageBase64(image: UIImage) -> String? {
    guard let pictData = UIImagePNGRepresentation(image) else {
        return nil
    }
    let strBase64: String = pictData.base64EncodedString(options: [])
    return strBase64
}

EDIT 2* And the php file for storing:

<?php
$userid=$_POST["userid"];
$password=$_POST["password"];
$pass = md5($password);
$email=$_POST["email"];
$profilepicture=$_POST["profilepicture"];


$conn = mysqli_connect(connection);

if ($conn->connect_error) {
 die("Connection failed: " . $conn->connect_error);
} 

$sql =("UPDATE users SET password='".$pass."' ,  email='".$email."' , profilepicture='".$profilepicture."' WHERE id=".$userid."");

if ($conn->query($sql) === TRUE) {
    echo "Record updated successfully";
} else {
    echo "Error updating record: " . $conn->error;
}

$conn->close();
?>

this is a similar question to this , but even trying all the answers did not work for me. The response I'm getting is right but I can't encode it, since Im always getting nil trying to encode:

I have tried a lot of things like this too:

Decode base64_encode Image from JSON in Swift

EDIT 1

The string im receiving has the following prefix: "[{\\"profilepicture\\":\\"iVBORw0KGgoAAAANSUhE...

Is it possible to convert the string without this prefix or is the prefix not even relevant to convert the string?

EDIT 2

Your server side code returns JSON data containing an array of assoc arrays retrieved with fetch_assoc() .

I recommend you to update the server side code, as it returns some other things than an image data, it should better send only the image data.

But if you want to use the server side code as is, you may need to write something like this in your loadImage :

    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {
            print("error=\(error?.localizedDescription ?? "nil")")
            return
        }

        guard let httpResponse = response as? HTTPURLResponse else {
            print("response is not an HTTPURLResponse")
            return
        }
        guard httpResponse.statusCode == 200 else {
            print("statusCode should be 200, but is \(httpResponse.statusCode)")
            print("response = \(httpResponse)")
            return
        }

        do {
            //First decode the response body as JSON
            let json = try JSONSerialization.jsonObject(with: data)
            //The decoded object should be a JSON array containing one JSON object
            guard let arr = json as? [[String: Any]], !arr.isEmpty else {
                print("json is not an array, or is empty")
                return
            }
            //Use only the first record
            let person = arr[0]
            //Retrieve the column value of "profilepicture" in the first record
            guard let encodedImage = person["profilepicture"] as? String else {
                print("NO profilepicture")
                return
            }
            //Decode it into binary data as Base64
            guard let imageData =  Data(base64Encoded: encodedImage, options: .ignoreUnknownCharacters) else {
                print("encodedImage is not a valid Base64")
                return
            }
            //Convert the decoded binary data into an image
            guard let image = UIImage(data: imageData) else {
                print("imageData is in a unsupported format or is not an image")
                return
            }
            print(image.size)
            //Use `image` here...
        } catch {
            print(error)
        }
    }
    task.resume()

You may need to modify some parts, but you can easily find where to fix as I embedded many print in bad cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM