如何将图像转换为位图并使用 Alamofire 上传?

How to convert Image to Bitmap and upload with Alamofire?

我想通过将数据附加到请求正文来使用 Alamofire 将数据和图像发送到我的数据库。现在我已经成功插入了所有数据,但没有插入图像(图像没有插入到数据库中)。图片来自.photoLibrary.camera,然后将其转换为位图字符串数据,然后将图片发送到服务器。如何使用alamofire将转换后的位图图像插入数据库?

这是我的 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()! })
}

我从这里得到了 convertToJpegData

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
            }
        }
    }
}

如果您期望成功时出现空响应,则服务器需要 return 适当的 204 / 205 响应,或者您需要告诉您的响应处理程序允许您执行任何代码 return 为空 body。例如,如果您收到 200:

.responseJSON(emptyResponseCodes: [200, 204, 205]) { response in

}

好的,我终于找到了答案。我不能使用数据插入我的图像,而是我必须再次将它转换为字符串以便 post 它到服务器。

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

感谢大家的帮助!