ios - 上传图片到服务器时出现绿线

标签 ios swift

我有一个 iOS 应用程序,允许使用下面的 Swift 函数将图像上传到 Ubuntu 服务器(使用 Apache Web 服务器):

private func uploadPhoto(image:UIImage) {
    let imageData = image.jpegData(compressionQuality: 0.6)
    if imageData == nil {
        NSLog("Image Data is nil")
    } else {
        let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
        let url = URL(string: "https://example.com/myapi.php")!
        var request = URLRequest(url: url)
        request.addValue("application/json", forHTTPHeaderField: "Accept")
        request.httpMethod = "POST"
        
        let boundary = NSUUID().uuidString
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        
        let body = NSMutableData()
        // Text Parameter: Action
        body.append(NSString(format: "--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
        body.append(NSString(format: "Content-Disposition: form-data; name=\"action\"\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
        body.append(NSString(format: "some_text_data\r\n").data(using: String.Encoding.utf8.rawValue)!)
        
        // Text Parameter: Build Number
        body.append(NSString(format: "--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
        body.append(NSString(format: "Content-Disposition: form-data; name=\"build\"\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
        body.append(NSString(format: ("\(buildNumber ?? "99999")\r\n" as NSString)).data(using: String.Encoding.utf8.rawValue)!)
        
        // File Parameter
        body.append(NSString(format: "--%@\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
        body.append(NSString(format:"Content-Disposition: form-data; name=\"the_img\"; filename=\"image.jpg\"\r\n").data(using: String.Encoding.utf8.rawValue)!)
        body.append(NSString(format: "Content-Type: application/octet-stream\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
        body.append(imageData!)
        body.append(NSString(format: "\r\n--%@--\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
        
        request.httpBody = body as Data
        
        let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            guard error == nil else {
                return
            }
            
            guard let data = data else {
                return
            }
            
            do {
                //create json object from data
                if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
                    print(json)
                }
            } catch let error {
                print(error.localizedDescription)
            }
        })
        task.resume()
    }
}

上传功能正常,图片上传到服务器没有错误。但是,某些上传的图像(大约十分之一)在上传图像的缩略图(在 macOS 10.15.6 Finder 的快速预览中显示)上会出现绿线;好像 JPEG 已损坏。请参阅下面的屏幕截图示例:

screenshot of quick preview

但是图像本身似乎没有问题:

original photo

为什么会发生这种情况?如果将 image.jpegData(compressionQuality:) 设置为 1.0(无压缩),则根本不会发生此问题。我是否错误地进行了图像压缩?

最佳答案

您需要检查图像的整个流程,并查看损坏发生的具体位置。

根据您发布的内容,您有一个UIImage,它是图像的内存表示形式。您声称这张图片看起来不错。

下一步是使用 image.jpegData(compressionQuality: 0.6) 将图像编码为标准格式 JPEG。结果是可写入文件的数据,并且可以由任何支持打开 JPEG 图像的应用程序打开。我建议您尝试将其写入某个文件(Data 有一个使用 FileManager.default 的写入选项),或者您也可以快速尝试将其发送到您的计算机直接使用activity controller .

如果此步骤产生损坏的图像,则 iOS 上的编码器存在问题,但我希望情况并非如此。但如果是这样,请提交错误报告并尝试使用不同的压缩质量或不同的格式(PNG,如果可能)。

在此部分之后,您将原始 JPEG 数据注入(inject)到 HTTP 请求的正文中。没有什么特别的。数据应按原样传送到服务器,并且传输中发生损坏的机会太接近于零,不可能在一生中见证损坏。因此,在这部分之后,您需要检查服务器上发生了什么。

如果服务器上没有发生任何事情,那么下载 JPEG 应该会生成与发送到服务器的数据完全相同的数据。您可以通过将数据 imageData 与下载的数据进行比较来检查这一点(只需使用 try!Data(contentsOf: URL(string: "your URL here")!))。

如果数据不相同(这是我现在所期望的),您应该分析服务器端发生的情况。发生这种损坏似乎很奇怪,但可能存在一些不兼容的设置。有时解决方案非常不直观;例如,您还需要随您的请求发送 mime 类型。我认为您的情况应该是 image/jpeg

此外,从我们看到的异常情况来看,我怀疑“每行字节数”存在兼容性问题。有时出于性能原因,会在每条“行”的末尾添加额外的填充。当不被忽略时,填充将被带入下一行。在损坏的图像中,您可以看到第一行正常,而第二行以绿色异常开头。第三行将异常向前移动了另一个相等的长度。不确定这些信息是否对您有帮助,但这是处理图形纹理(例如使用 openGL 时)时的常见问题。

关于ios - 上传图片到服务器时出现绿线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64002532/

相关文章:

compare - 在 Swift 中比较字符

ios - 提取 childView 并将其重新定位到新的 parentView 中

ios - Xcode Swift 计算 23 个文本字段值的平均值

ios - Swift 编译器在handleDeferredImports 中出现段错误

ios - 如何在 iOS 上获取 "internet time"?

ios - Firebase 快速作为 OS X 的后端服务

ios - UIViewController 变量在解除分配后仍然存在

objective-c - iOS 在设备旋转时更改自动布局约束

ios SWRevealViewController 显示推送 segue 动画

ios - 在应用程序启动时启动保存的状态(快速)