Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alamofire upload huge file

I am using Alamofire to upload assets (image/video) as multipart form data. It works fine for file sizes below 300MB (app). When I try to upload a file greater than 300MB, app crashes.

if let video = self.avPlayerItem?.asset as? AVURLAsset {
    if let assetData = NSData(contentsOfURL: video.URL) {
        multipartFormData.appendBodyPart(data: assetData, name: "file", fileName: "video", mimeType: "video/mp4") // Execution stops here
    }
}

I also get the below message from Xcode

enter image description here

How would I support uploading huge sized videos using Alamofire?

like image 244
iOS Avatar asked Nov 03 '16 09:11

iOS


2 Answers

Use Stream to upload instead of converting file to NSData which lead to memory problem and occur crash while uploading huge files. sample code

  if let imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL{
        let assetLibrary = ALAssetsLibrary()
        assetLibrary.assetForURL(imageUrl , resultBlock: { (asset: ALAsset!) -> Void in
            if let actualAsset = asset as ALAsset? {
                let assetRep: ALAssetRepresentation = actualAsset.defaultRepresentation()

                let size = assetRep.size()
                let stream = NSInputStream(URL: assetRep.url())

                Alamofire.upload(
                    .POST,
                    "SERVER_URL",
                    headers: [:],
                    multipartFormData: { multipartFormData in

                         multipartFormData.appendBodyPart(stream: stream!, length: UInt64(size), name: "fileparameter", fileName: "fileName", mimeType: "video/mp4")

                    },
                    encodingCompletion: { encodingResult in
                        switch encodingResult {
                        case .Success(let upload, _, _):
                            upload.progress { bytesWritten, totalBytesWritten, totalBytesExpectedToWrite in
                                dispatch_async(dispatch_get_main_queue()) {
                                    let percent = (Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))
                                    print(percent)
                                }
                            }
                            upload.validate()
                            upload.responseJSON { response in
                                print(response);
                            }
                        case .Failure(let encodingError):
                            print(encodingError)
                            let error = NSError(domain: "", code: 404, userInfo: [NSLocalizedDescriptionKey: "Image Uploading Failed. Please try again."])
                            let result = Result<AnyObject, NSError>.Failure(error)
                            let response = Response(request: nil, response: nil, data: nil, result: result)
                             print(response);

                        }
                    }
                )

            }
            }, failureBlock: { (error) -> Void in
        })
    }
like image 131
MAhipal Singh Avatar answered Oct 02 '22 15:10

MAhipal Singh


Alamofire Documentation

Uploading Data to a Server When sending relatively small amounts of data to a server using JSON or URL encoded parameters, the request() APIs are usually sufficient. If you need to send much larger amounts of data from Data in memory, a file URL, or an InputStream, then the upload() APIs are what you want to use.

Uploading Data

let data = Data("data".utf8)

AF.upload(data, to: "https://httpbin.org/post").responseJSON { response in
    debugPrint(response)
}

Uploading a File

let fileURL = Bundle.main.url(forResource: "video", withExtension: "mov")

AF.upload(fileURL, to: "https://httpbin.org/post").responseJSON { response in
    debugPrint(response)
}

Uploading Multipart Form Data

AF.upload(multipartFormData: { multipartFormData in
    multipartFormData.append(Data("one".utf8), withName: "one")
    multipartFormData.append(Data("two".utf8), withName: "two")
}, to: "https://httpbin.org/post")
    .responseJSON { response in
        debugPrint(response)
    }

Upload Progress While your user is waiting for their upload to complete, sometimes it can be handy to show the progress of the upload to the user. Any UploadRequest can report both upload progress of the upload and download progress of the response data download using the uploadProgress and downloadProgress APIs.

let fileURL = Bundle.main.url(forResource: "video", withExtension: "mov")

AF.upload(fileURL, to: "https://httpbin.org/post")
    .uploadProgress { progress in
        print("Upload Progress: \(progress.fractionCompleted)")
    }
    .downloadProgress { progress in
        print("Download Progress: \(progress.fractionCompleted)")
    }
    .responseJSON { response in
        debugPrint(response)
    }
like image 45
MoD Avatar answered Oct 02 '22 15:10

MoD