skip to Main Content

I want to send the data as well as image to my database with Alamofire, by appending the data to the request body. Now I’ve successfully inserted all the data, but not the image (the image is not inserted to the database). The image comes from .photoLibrary or .camera and then convert it as bitmap string data before send the image to the server. How to insert converted bitmap image to the database with alamofire?

Here is my ContentView

import SwiftUI
import UIKit
import Alamofire
import MobileCoreServices

struct ContentView: View {
    
    @State var chassisNumber = ""
    @State var engineNumber = ""
    @State var lisencePlate = ""
    @State var carYear = ""
    @State var carModel = ""
    @State var vehiclePicture = ""
    @State var imageSelected: UIImage
    @State var sourceType: UIImagePickerController.SourceType = .camera
    @State var showImagePicker = false
    
    @AppStorage("userEmail") var currentUserEmail: String?
    
    var body: some View {
        VStack{
            Button(action: {
                sourceType = UIImagePickerController.SourceType.photoLibrary
                self.showImagePicker = true
            }, label: {
                Text("Choose Image")
            })
            
            TextField("Car Model", text: $carModel)
            TextField("Car Year", text: $carYear)
            TextField("Chassis Number", text: $chassisNumber)
            TextField("Engine Number", text: $engineNumber)
            TextField("Lisence Plate", text: $lisencePlate)
            
            Button(action: {
                vehiclePicture = randomString(length: 25)
                insertNewVehicle(EMAIL: currentUserEmail ?? "Empty", NAMA_MODEL: carModel, TAHUN_PRODUKSI: carYear, CHASSISNO: chassisNumber, ENGINENO: engineNumber, NOPOL: lisencePlate, VEHICLE_PICTURE: vehiclePicture, ENCODED_IMG: imageSelected)
            }, label: {Text("Save"})
            
        }
        .sheet(isPresented: $showImagePicker){
            ImagePicker(imageSelected: $imageSelected, sourceType: $sourceType)
        }
    }
}

func insertNewVehicle(EMAIL: String, NAMA_MODEL: String, TAHUN_PRODUKSI: String, CHASSISNO: String, ENGINENO: String, NOPOL: String, VEHICLE_PICTURE: String, ENCODED_IMG: UIImage?){
    
    let parameters = ["EMAIL": EMAIL, "NAMA_MODEL": NAMA_MODEL, "TAHUN_PRODUKSI": TAHUN_PRODUKSI, "CHASSISNO": CHASSISNO, "ENGINENO": ENGINENO, "NOPOL": NOPOL, "VEHICLE_PICTURE": VEHICLE_PICTURE]
    
    AF.upload(multipartFormData: { multipartFormData in

            for (key,value) in parameters {
                multipartFormData.append((value).data(using: .utf8)!, withName: key)
            }
        
            // Upload image to server << image is not inserted
            guard let image = ENCODED_IMG else { return }
            let jpegData = image.toJpegData(compressionQuality: 0.4)
            multipartFormData.append(Data((jpegData)!), withName: "ENCODED_IMG")
        

    }, to: "http://myapi")

        .responseJSON { response in
            // Check whether chassis number is exist or not
            if let data = response.data, let string = String(data: data, encoding: .utf8){
                
                // If chassis number is exist
                print(string)
                
            }else{
                
                // If chassis number is not exist
                print("Chassis not exists, inserting data...")
                
            }
    }
}

func randomString(length: Int) -> String {
  let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
  return String((0..<length).map{ _ in letters.randomElement()! })
}

I got convertToJpegData from here https://stackoverflow.com/a/55839062/15132219

extension UIImage {

    func toJpegData (compressionQuality: CGFloat, hasAlpha: Bool = true, orientation: Int = 6) -> Data? {
        guard cgImage != nil else { return nil }
        let options: NSDictionary =     [
            kCGImagePropertyOrientation: orientation,
            kCGImagePropertyHasAlpha: hasAlpha,
            kCGImageDestinationLossyCompressionQuality: compressionQuality
        ]
        return toData(options: options, type: .jpeg)
    }

    func toData (options: NSDictionary, type: ImageType) -> Data? {
        guard cgImage != nil else { return nil }
        return toData(options: options, type: type.value)
    }

    // about properties: https://developer.apple.com/documentation/imageio/1464962-cgimagedestinationaddimage
    func toData (options: NSDictionary, type: CFString) -> Data? {
        guard let cgImage = cgImage else { return nil }
        return autoreleasepool { () -> Data? in
            let data = NSMutableData()
            guard let imageDestination = CGImageDestinationCreateWithData(data as CFMutableData, type, 1, nil) else { return nil }
            CGImageDestinationAddImage(imageDestination, cgImage, options)
            CGImageDestinationFinalize(imageDestination)
            return data as Data
        }
    }

    // https://developer.apple.com/documentation/mobilecoreservices/uttype/uti_image_content_types
    enum ImageType {
        case image // abstract image data
        case jpeg                       // JPEG image
        case jpeg2000                   // JPEG-2000 image
        case tiff                       // TIFF image
        case pict                       // Quickdraw PICT format
        case gif                        // GIF image
        case png                        // PNG image
        case quickTimeImage             // QuickTime image format (OSType 'qtif')
        case appleICNS                  // Apple icon data
        case bmp                        // Windows bitmap
        case ico                        // Windows icon data
        case rawImage                   // base type for raw image data (.raw)
        case scalableVectorGraphics     // SVG image
        case livePhoto                  // Live Photo

        var value: CFString {
            switch self {
            case .image: return kUTTypeImage
            case .jpeg: return kUTTypeJPEG
            case .jpeg2000: return kUTTypeJPEG2000
            case .tiff: return kUTTypeTIFF
            case .pict: return kUTTypePICT
            case .gif: return kUTTypeGIF
            case .png: return kUTTypePNG
            case .quickTimeImage: return kUTTypeQuickTimeImage
            case .appleICNS: return kUTTypeAppleICNS
            case .bmp: return kUTTypeBMP
            case .ico: return kUTTypeICO
            case .rawImage: return kUTTypeRawImage
            case .scalableVectorGraphics: return kUTTypeScalableVectorGraphics
            case .livePhoto: return kUTTypeLivePhoto
            }
        }
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    Ok, I've finally found my answer. I can't use Data to insert my image, instead I have to convert it again to string in order to post it to server.

    let imageData: Data = imageSelected.jpegData(compressionQuality: 0.4) ?? Data()
    let encodedImage: String = imageData.base64EncodedString()
    

    Thanks for all the help!


  2. If you’re expecting an empty response on success, either the server needs to return the appropriate 204 / 205 response, or you need to tell your response handler to allow whatever code you do return with an empty body. For instance, if you received a 200:

    .responseJSON(emptyResponseCodes: [200, 204, 205]) { response in
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search