как отправить изображение в byteArray с параметрами в формате JSON iOS swift4

avatar
Venkatesh Chejarla
8 апреля 2018 в 10:29
1215
1
1

Я новичок в iOS, и у меня гораздо меньше знаний о программировании. Теперь в моем проекте я застрял с задачей, в которой мне нужно отправить данные создаваемого пользователя вместе с загрузкой изображения для камеры или из библиотеки фотографий. На самом деле я не знаю, как это сделать, я искал в Интернете, coderhelper и некоторых других блогах о том, как отправлять изображения с параметрами в swift4 и все еще пытаюсь понять процесс, и я пытаюсь это сделать уже неделю, я не знаю не знаю, что еще делать. Я публикую свой код здесь:

 @IBAction func createAccountTapped(_sender: UIButton!) {

        guard let image = profileImgView.image else {return}

        let imageData = UIImageJPEGRepresentation(image, 0.7)
        print(imageData!)

        let byteArray = Array(imageData!)

        let updateProfileUrl = "http://isit.beetlerim.com/api/UsersAPI/UpdateUserProfile"

        let parameters = [
            "UserName":userNameTF.text! 
            "Password":passwordTF.text! 
            "UserTypeId":2,
            "profilePic":"\(arc4random()).jpg",
            "profileImage":byteArray,
            "DOB":dateOfBirthTF.text! 
            "PhoneNumber":phoneNumberTF.text! 
            "Mobile":phoneNumberTF.text! 
            "Email":emailAddressTF.text! 
            "AddressLine1":address1TF.text! 
            "AddressLine2":address2TF.text! 
            "City":cityTF.text! 
            "State":stateTF.text! 
            "Country":countryTF.text! 
            "ZipCode":zipcodeTF.text!
            ] as [String : Any]

        let jsonData = try? JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)

        print(jsonData!)

        // create post request
        let url = URL(string: updateProfileUrl)!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"

        // insert json data to the request
        request.httpBody = jsonData
        request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accpet")
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                print(error?.localizedDescription ?? "No data")
                return
            }
            let responseJSON = try? JSONSerialization.jsonObject(with: data, options: .allowFragments )
            if let responseJSON = responseJSON as? [String: Any] {
                print(responseJSON)
            }
        }

        task.resume()
    }

Я получаю responseJSON: ["сообщение": Произошла ошибка.] }

Я также пробовал много других способов.. ни один из них не сработал.. пожалуйста, помогите мне, ребята:

Источник
OOPer
8 апреля 2018 в 11:48
0

Сообщение об ошибке ясно говорит 'multipart/form-data' не поддерживается, и вы все еще пытаетесь использовать multipartFormData? Лучше проверьте спецификацию API.

Venkatesh Chejarla
8 апреля 2018 в 13:40
0

@OOper, не могли бы вы объяснить, как отправить изображение с параметрами в формате application/json ..

VIP-DEV
8 апреля 2018 в 15:12
0

Нам нужно установить в заголовке http тип изображения, т.е. png или jpeg.

Venkatesh Chejarla
9 апреля 2018 в 02:32
0

@VIP-DEV Я сделал это там как headers: ["Content-Type" : "application/json"], все равно безрезультатно..

Venkatesh Chejarla
9 апреля 2018 в 02:34
0

@OOper Мне интересно, могу ли я спросить наших разработчиков на стороне сервера, какие данные они принимают, и убедиться, что я отправляю их именно так.

Venkatesh Chejarla
9 апреля 2018 в 07:24
0

@OOper попросили прислать изображение с параметрами в формате json. Но везде в инете я вижу только multipart/form-data для этого сценария

OOPer
9 апреля 2018 в 09:05
0

Есть серверы, которые принимают изображения в формате JSON, обычно base64 или иногда hex. (Включать большие данные в JSON, на мой взгляд, плохой дизайн. Лучше найти лучших инженеров на стороне сервера.) Предполагая base64, видя ваш parameters, который уже включает строку "profilePic": base64String,, вам просто нужно использовать обычный Alamofire запрос, чем upload(multipartFormData:). Я никогда не использовал Alamofire в своих приложениях, но я думаю, что вы можете сделать это самостоятельно, или кто-то может помочь, если вы обновите свой вопрос, включая то, что они попросили меня отправить изображение с параметрами в формате json.

Venkatesh Chejarla
9 апреля 2018 в 09:36
0

@OOper спасибо за ответ, приятель, это очень полезно. И мой инженер на стороне сервера просит отправить изображение в byteArray, а не в base64String. Я думаю, что let imageData = UIImageJPEGRepresentation(profileImgView.image!, 0.7) эта строка кода преобразует его в byteArray.. Хотя не уверен..

OOPer
9 апреля 2018 в 10:05
0

Массив байтов в JSON... Невероятно... imageData в вашем коде становится Data?, а не массив байтов. В С# массив байтов эквивалентен Swift Array<UInt8>, вы можете сделать это с помощью let byteArray = Array(imageData!). В Java массив байтов, Swift Array<Int8> немного сложнее: let byteArray = Array(imageData!.lazy.map{Int8(bitPattern: $0)}). Могут быть некоторые возможные случаи, но это известно только вашим инженерам на стороне сервера.

Venkatesh Chejarla
9 апреля 2018 в 11:35
0

@OOper Я сделал, как вы сказали, но когда я пытаюсь отправить изображение, я получаю сообщение об успешном завершении как ["сообщение": произошла ошибка.]. Я не знаю, что я делаю неправильно. Я отредактирую свой вопрос.

OOPer
9 апреля 2018 в 12:16
0

Кажется, мне просто нужно повторить: знает только инженеров вашей серверной части. Как вы видите, в сообщении об ошибке нет информации об ошибке. JSON генерируется сервером, а не вашим кодом или iOS.

OOPer
10 апреля 2018 в 00:00
0

В вашем вопросе отсутствует важная информация. 'multipart/form-data' не поддерживается. попросили прислать картинку с параметрами в формате json. мой серверный инженер просит отправить изображение в byteArray, а не в base64String. Не многие читатели читают длинные комментарии.

Venkatesh Chejarla
10 апреля 2018 в 08:02
0

@OOper Большое спасибо за руководство в этом процессе.. Я узнал кое-что новое от вас и «Ааоли».. Они попросили меня отправить byte[], но это не сработало.. но я попробовал способ «Aaoli», отправив его в base64. Бог! это сработало... похоже, наши серверные инженеры понятия не имеют, что они делают... В любом случае, большое вам спасибо, ребята.

OOPer
10 апреля 2018 в 08:48
0

Рад слышать, что вы нашли решение. Вы должны отметить одну вещь: даже если иногда инженеры на стороне сервера используют неправильную терминологию, очень важно общаться с людьми на стороне сервера, чтобы написать правильный коммуникационный код. Удачи.

Venkatesh Chejarla
10 апреля 2018 в 10:21
0

@OOper Конечно, братан.. Спасибо..

Ответы (1)

avatar
AaoIi
9 апреля 2018 в 13:39
1

Прежде всего вам нужно убедиться, что размер изображения меньше максимального размера со стороны сервера, и это один из способов, о котором сервер может сообщить вам, но вам все равно придется отлаживать его на стороне сервера. скажем, в основном он ограничен 2 МБ, как обычно.

Поэтому вам нужно сначала изменить его размер, а затем преобразовать в base64, но это не предпочтительный способ загрузки изображений, поскольку он увеличивает размер передаваемых данных на 33%. На стороне сервера следует использовать multipart/form-data, поскольку это стандартный способ передачи двоичных данных по HTTP. Но вот:

let imageResized = image.resizeWith(percentage: 0.1)
let base64 = imageResized?.toBase64()

Вам необходимо использовать следующие расширения:

extension UIImage {
    func resizeWith(percentage: CGFloat) -> UIImage? {
        let imageView = UIImageView(frame: CGRect(origin: .zero, size: CGSize(width: size.width * percentage, height: size.height * percentage)))
        imageView.contentMode = .scaleAspectFit
        imageView.image = self
        UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        imageView.layer.render(in: context)
        guard let result = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
        UIGraphicsEndImageContext()
        return result
    }
}

extension UIImage {
    
    func toBase64() -> String? {
        
        let imageData : NSData = UIImageJPEGRepresentation(self, 1.0)! as NSData
        return imageData.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength64Characters)
    }
}

Наконец, отправьте свой параметр следующим образом:

let parameters = [
            "UserName":userNameTF.text! 
            "Password":passwordTF.text! 
            "UserTypeId":2,
            "profilePic":"\(arc4random()).png",
            "profileImage":base64! 
            "DOB":dateOfBirthTF.text! 
            "PhoneNumber":phoneNumberTF.text! 
            "Mobile":phoneNumberTF.text! 
            "Email":emailAddressTF.text! 
            "AddressLine1":address1TF.text! 
            "AddressLine2":address2TF.text! 
            "City":cityTF.text! 
            "State":stateTF.text! 
            "Country":countryTF.text! 
            "ZipCode":zipcodeTF.text!
            ] as [String : Any]

Надеюсь, это сработает!

Venkatesh Chejarla
10 апреля 2018 в 07:57
1

@Ааоли О боже!!! Это адская строка.. она сработала.. Большое спасибо за это. Я буду у тебя в долгу...