如何将 UIImage 转换为 .JPEG 格式并将其发送到服务器?

Posted

技术标签:

【中文标题】如何将 UIImage 转换为 .JPEG 格式并将其发送到服务器?【英文标题】:How to convert UIImage to .JPEG format and send it to a server? 【发布时间】:2020-06-05 07:14:47 【问题描述】:

我正在构建一个可以将.jpeg 文件发送到服务器的应用程序。所以我想做的是我有一个控制器来拍照并将照片发送到服务器。当然,第一个照片格式是UIImage,当我将它发送到服务器时它不起作用,因为服务器不接受UIImage 文件类型。所以我做了一些研究,发现了将UIImage转换为.jpeg文件格式的函数,如下所示:

let photoJpg = self.photo?.jpegData(compressionQuality: 1.0)

我将 photoJpg 变量传递给 API 调用函数,但 API 一直拒绝我的请求,在调用 API 时说 500 状态代码。所以我猜我可能不会以正确的方式转换文件。那么如何将UIImage 转换为.jpeg 文件格式,将其存储到变量中并将其发送到API?如果您需要更多信息,请随时询问,我会提供给您。谢谢。

编辑:调用 API 的函数

func submitPhoto() 
        let headers = ["authorization": registerData!.token]
        let photoJpg = self.photo?.jpegData(compressionQuality: 1.0)

        let params: [String: Any] = [
            "files": photoJpg!
        ]

        Webservice.Request(url: Webservice.SUBMIT_PHOTO, method: Webservice.HttpMethod.post, parameters: params, headers: headers, loading: true, loadingString: nil, success:  (response) in
            print("Submit photo success")
        )  (response) in
            print("Submit photo failed")
        
    

Webservice类中的Request函数

class func Request(url: String, method: HttpMethod, parameters: [String: Any], headers: [String:String], loading: Bool, loadingString: String?, success: @escaping (JSON) -> Void, failure: @escaping (Error) -> Void) 
        if manager == nil 
            let urlConfig = URLSessionConfiguration.default
            urlConfig.timeoutIntervalForRequest = KPMConfig.RTO_TIME
            manager = SessionManager(configuration: urlConfig)
        
        let request = manager.request(url, method: method == .post ? HTTPMethod.post : HTTPMethod.get, parameters: parameters, encoding: URLEncoding.default, headers: headers)
        if loading 
            ProgressHUD.show(loadingString, interaction: false)
        
        print("-url: \n\(url)")
        print("-params: \n\(parameters)")
        print("-headers: \n\(headers)")
        request.responseJSON  (response) in
            if loading 
                ProgressHUD.dismiss()
            
            switch response.result 
            case .success(let values):
                let data = JSON(values)
                print("response: \n\(data)")
                switch data["code"].intValue 
                case 200...203:
                    success(data)
                case 400...403:
                    let errorDetails = Error(
                        error: ErrorModel(code: data["error"]["code"].stringValue,
                                     message: data["error"]["message"].stringValue,
                                     target: data["error"]["target"].stringValue,
                                     details: data["error"]["details"]),
                        code: data["code"].intValue)
                    failure(errorDetails)

                        if data["code"].intValue == 401 
                            print("-url: \n\(url)")
                            self.removeUserData()
                            self.goToLoginPage()
                        

                case 500:
                    let errorDetails = Error(
                        error: ErrorModel(code: data["error"]["code"].stringValue,
                                     message: data["error"]["message"].stringValue,
                                     target: data["error"]["target"].stringValue,
                                     details: data["error"]["details"]),
                        code: data["code"].intValue)
                    failure(errorDetails)
                default:
                    break
                
            case .failure(let values):
                let data = JSON(values)
                print("-response: \n\(data)")
                let errorDetails = Error(
                    error: ErrorModel(code: data["error"]["code"].stringValue,
                                 message: data["error"]["message"].stringValue,
                                 target: data["error"]["target"].stringValue,
                                 details: data["error"]["details"]),
                    code: data["code"].intValue)    
                failure(errorDetails)
            
        
    

【问题讨论】:

这能回答你的问题吗? How to upload images to a server in ios with Swift? 500 错误是内部服务器错误,并不一定意味着您的请求是错误的。也就是说,我们需要更多信息来诊断这一点。谁负责服务器,你建的吗?你是如何调用 API 的? self.photo 不是 nil 吗?您有权访问服务器日志吗? @EmilioPelaez 不幸的是,我不是制作服务器的人,也不是负责它的人。我通过调用已经提供的函数将数据发送到服务器来调用 api “你如何调用 API”我的意思是我们需要查看代码。如果我们没有看到它,我们无法帮助您修复您的代码。 @EmilioPelaez 抱歉没有说得更清楚,我添加了更多代码供您阅读 【参考方案1】:

您需要将图像保存在文档目录中然后您可以将 jpeg 文件发送到服务器,因为这是您需要做的。

func saveImageAndGetData(name: String, image: UIImage) -> Data? 


     guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else  return nil

  let fileName = name
  let fileURL = documentsDirectory.appendingPathComponent(fileName)
   guard let data = image.jpegData(compressionQuality: 1) else  return nil


//Checks if file exists, removes it if so.
  if FileManager.default.fileExists(atPath: fileURL.path) 
    do 
        try FileManager.default.removeItem(atPath: fileURL.path)
        print("Removed old image")
     catch let removeError 
        print("couldn't remove file at path", removeError)
    



  do 
    try data.write(to: fileURL)
   catch let error 
    print("error saving file with error", error)
  
     return data

这样获取数据

if let imageData = saveImageAndGetData(name: "name", image: UIImage(named: "image")!) 


加载图片

func loadImageFromDisk(fileName: String) -> UIImage? 

  let documentDirectory = FileManager.SearchPathDirectory.documentDirectory

    let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
    let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)

    if let dirPath = paths.first 
        let imageUrl = URL(fileURLWithPath: dirPath).appendingPathComponent(fileName)
        let image = UIImage(contentsOfFile: imageUrl.path)
        return image

    

    return nil

【讨论】:

是的,它对我不起作用。我收到此错误消息"The file couldn’t be saved because the specified URL type isn’t supported." 当你更新你的答案时,为什么不把“你可以这样做”改成更具描述性和意义的东西 @jawadAli 我假设这个功能只是保存文件?有没有办法在将文件发送到服务器之前获取文件?【参考方案2】:

编辑:getDocumentsDirectory 函数是这样的:

func getDocumentsDirectory() -> URL 
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory

您发布的代码为您提供 JPEG 数据而不是 JPEG 文件,您仍然需要将其保存到文件中,如下所示:

if let data = image.jpegData(compressionQuality: 0.8) 
    let jpegFile = getDocumentsDirectory().appendingPathComponent("copy.jpg")
    try? data.write(to: filename)

然后您可以将 jpegFile 发送到服务器,因为这是您需要做的。

【讨论】:

调用getDocumentsDirectory() 函数时出现unresolved identifier 错误 检查更新的代码。抱歉没有早点说清楚,getDocumentsDirectory 是一个函数

以上是关于如何将 UIImage 转换为 .JPEG 格式并将其发送到服务器?的主要内容,如果未能解决你的问题,请参考以下文章

将每个TIFF帧转换为JPEG格式,并使用Java将其转换为PDF格式

怎样将jpeg转换bitmap

如何才能将jpg格式的图片转化成png格式的

将UIImage转换为NSData并返回UIImage

如何使用干预图像laravel将webp图像转换为jpeg或png

将 grib 文件转换为 netcdf(jpeg 格式)