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
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.
Thanks for all the help!
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: