iOS Swift + Alamofire 上传带有 exif 数据的照片

Posted

技术标签:

【中文标题】iOS Swift + Alamofire 上传带有 exif 数据的照片【英文标题】:iOS Swift + Alamofire upload photos with exif data 【发布时间】:2016-08-22 16:41:52 【问题描述】:

我正在使用Alamofire 使用their REST API 将多个文件同时上传到Open Asset,我能够让它工作,但是,大部分EXIF 数据都被删除了。不幸的是,EXIF 数据是必须的,因为我们需要能够通过各种 Web 客户端挖掘 GPS 标签和其他一些东西。

在做了一些研究后,我发现问题是因为我正在使用 UIImageJPEGRepresentation 将照片转换为 NSData(这是 Alamofire 所期望的或 fileURL,我认为这不会适用我?)。

我还使用BSImagePicker 库来允许用户拍摄/选择多张照片,它返回一个PHAssets 数组,然后将其转换为NSData。这是我的功能(其中collectedImages 是一个全局字典):

func compressPhotos(assets: [PHAsset]) -> Void 
        for asset in assets 
            let filename = self.getOriginalFilename(asset)
            let assetImage = self.getAssetPhoto(asset)

            let compressedImage = UIImageJPEGRepresentation(assetImage, 0.5)!  // bye bye metadata :(
            collectedImages[filename] = compressedImage
            print("compressed image: \(filename)")
        
    

如果我可以使用从PHAsset 到手机本地图像的完整路径,我想我可以保留 EXIF 数据,但Alamofire 似乎不支持这一点。我希望我错了。这是我的上传者:

func uploadPhotos(projectId: String, categoryId: String, data: [String: NSData], completionHandler: (AnyObject?, NSError?) -> ()) 
        var jsonBody = [AnyObject]()  //lazy
        Alamofire.upload(
            .POST,
            self.url + "/Files",
            multipartFormData:  multipartFormData in
                for (filename, img) in data 
                    jsonBody.append(["project_id": projectId, "category_id": categoryId, "original_filename": filename])
                    multipartFormData.appendBodyPart(data: img, name: "file", fileName: filename, mimeType: "image/jpeg")
                    print("img size: \(img.length)")

                
                let jsonData = jsonToNSData(jsonBody)
                print("_jsonBody: \(jsonBody)")
                multipartFormData.appendBodyPart(data: jsonData!, name: "_jsonBody")
                print("multipart: \(multipartFormData)")
            ,
            encodingCompletion:  encodingResult in
                switch encodingResult 
                case .Success(let upload, _, _):
                    upload.responseJSON  response in
                        debugPrint(response)
                        switch response.result 
                        case .Success(let value):
                            completionHandler(value as? NSArray, nil)
                        case .Failure(let error):
                            completionHandler(nil, error)
                        

                    
                case .Failure(let encodingError):
                    print(encodingError)
                
            
        )
    

所以我的问题是,如何在保留所有 EXIF 数据的同时上传多张照片(同时传递其他参数)? Alamofire 是一个很棒的库,我想在这里使用它,但如果我不能保留 EXIF 数据,我不会在上传过程中与它结婚。

【问题讨论】:

【参考方案1】:

我认为您可以先从 PHAsset 获取文件 URL,然后在调用 multipartFormData.appendBodyPart(...) 时使用该文件 URL。像这样的:

    从 PHAsset 获取 URL:

    [asset requestContentEditingInputWithOptions:editOptions
                           completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) 
    NSURL *imageURL = contentEditingInput.fullSizeImageURL;
    ];
    

    在 AlamoFire API 中使用文件 URL:

    multipartFormData.appendBodyPart(fileURL: imageURL, name: "image")

【讨论】:

啊,这听起来很有希望,但它不起作用......现在我收到一个错误file URL is not reachable: file:///var/mobile/Media/DCIM/102APPLE/IMG_2469.JPG"。不知道为什么它无法访问?我刚刚检查了source code(第 255 行),这似乎是在检查 OS X 10.10 操作系统还是什么?我真的不知道那里发生了什么。【参考方案2】:

我不知道为什么我在使用 fullSizeImageURL 时遇到问题,但它确实引导我找到了正确的路径,因为我能够通过从文件路径中获取图像为 NSData 来实现这一点这个:

asset.requestContentEditingInputWithOptions(PHContentEditingInputRequestOptions())  (input, _) in
    let fileURL = input!.fullSizeImageURL?.filePathURL
    let data = NSData(contentsOfFile: fileURL!.path!)!

然后我将它作为data 参数传递给Alamofire.request()。这保留了所有原始照片元数据。

【讨论】:

以上是关于iOS Swift + Alamofire 上传带有 exif 数据的照片的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 alamofire 将多个 PDF 文件上传到服务器? #Swift 4 #IOS [重复]

使用 PHP 在 Swift 5 中使用 Alamofire 接收图像上传

使用多部分形式的 Swift IOS 进行流式上传

在 iOS 9 问题上使用 Alamofire 上传带有 URL 参数的图像

带参数的 Alamofire 4 Swift 3 GET 请求

Swift - Alamofire - 从照片库上传文件