0

I used Alamofire with MultiParts to upload images from my app to my server, but when I execute the process, my app's crashed with message:

"Terminated due to memory issue"

I knew the problem is that when I getUIImageFromPHAsset, it makes app creashed cause of memory error - my images are too large (80mb - 36 images). But I don't know how to fix it.

Here's the code:

Upload images to server:

self.getUIImageFromPHAsset(assets: self.phAssets, completion: { (images) in
      self.uploadingView.isHidden = false
      self.restApiManager.requestCreateProduct(username: _username, product: _product, images: images)
})

Get UIImage from PHAsset:

func getUIImageFromPHAsset(assets: [PHAsset], completion: @escaping ( (_ images:[UIImage]) -> ())) {
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    option.isSynchronous = true

    var array: [UIImage] = []
    let group = DispatchGroup()

    for asset in assets {
        group.enter()
        manager.requestImage(for: asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in
            if let thumbnail = result {
                array.append(thumbnail)
            }
            group.leave()
        })
    }
    group.notify(queue: .main) {
        completion(array)
    }
}

Alamofire upload:

func requestCreateProduct(username:String, product:ProductInfo,images: [UIImage]) {
    let url = BASE_URL + "requestCreateProduct"

    let parameters: Parameters = [
        "username": username,
        "productName": product.name,
    ]

    Alamofire.upload(multipartFormData: { multipartFormData in
        for (key, value) in parameters {
            multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
            print("\(key) - \(value)")
        }

        var count = 1;
        for image in images {
            multipartFormData.append(UIImageJPEGRepresentation(image, 1.0)!, withName: "files", fileName: String(count) + ".jpg", mimeType: "image/jpg")
            count = count + 1
        }
    }, to:url) { (result) in
        switch result {
        case .success(let upload, _, _):
            upload.uploadProgress(closure: { (progress) in
                print("Upload Progress: \(progress.fractionCompleted)")
                self.delegate?.updateProgressBar(value: Float(progress.fractionCompleted))
            })
            upload.responseJSON { response in
                print(response)
            }

        case .failure(let encodingError):
            debugPrint(encodingError)
        }
    }   
}
Khoa
  • 1,738
  • 1
  • 14
  • 21
  • 1
    See https://stackoverflow.com/a/25251943/669586. Ideally, use lower JPEG quality, e.g. `0.8` or downscale the image before converting to JPEG. – Sulthan Apr 07 '18 at 16:51
  • @Sulthan your idea is nice but sometimes I need to upload more than 50 images (>100mb). So thay, your idea can't solve my problem. Thank you. – Khoa Apr 08 '18 at 00:53
  • Did you ever solve this issue? – Rool Paap Sep 13 '19 at 14:14
  • Hi @Rool Paap, the solution is that I applied **Multipart-uploading** instead of uploading a dozen images/files at a time. So that, we don't need to load all images/files to memory anymore. – Khoa Sep 16 '19 at 04:52

0 Answers0