【问题标题】:How to convert Image to Bitmap and upload with Alamofire?如何将图像转换为位图并使用 Alamofire 上传?
【发布时间】:2021-07-23 12:16:18
【问题描述】:

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

这是我的内容视图

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

【问题讨论】:

  • toJpegData(compressionQuality:) 从何而来?
  • 对不起,我忘了补充。我已经编辑了我的问题
  • 错误是说响应没有返回任何httpBody。是不是应该寄回去?应该是什么反应?您能否验证您的图片未正确上传?
  • 如果我成功插入数据。响应将不返回任何内容,如果错误(数据库中存在机箱号)将返回字符串“机箱号已存在”。我不知道我是否正确上传图片代码,因为我从未尝试使用 alamofire 上传图片。在我的代码中,除了上传图片部分,所有数据都可以插入。
  • "如果我成功插入数据。响应将不返回任何内容" 您看到的错误是因为响应没有任何httpBody。所以我猜它成功了?你不能在服务器上检查图像是否可见?

标签: ios swift xcode alamofire swift5


【解决方案1】:

如果您希望成功时返回空响应,则服务器需要返回适当的 204 / 205 响应,或者您需要告诉响应处理程序允许您返回的任何代码都返回一个空主体。例如,如果您收到 200:

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

}

【讨论】:

    【解决方案2】:

    好的,我终于找到了答案。我不能使用 Data 插入我的图像,而是必须再次将其转换为字符串才能将其发布到服务器。

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

    感谢大家的帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-20
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 2014-01-26
      • 2015-02-17
      • 1970-01-01
      相关资源
      最近更新 更多