6

I need to send zip file to server side.

There is my request which I need to work in background

let configuration = URLSessionConfiguration.default
    configuration.timeoutIntervalForRequest = 10 // seconds
    alamoFireManager = Alamofire.SessionManager(configuration: configuration)

appDeligate.log.debug("request was sended")

    alamoFireManager.upload(deligate.data!,
                            to: deligate.url,
                            method: .post,
                            headers: headers)
        .uploadProgress(closure: {
            progress in
            print("Upload Progress: \(progress.fractionCompleted)")
        })
        .validate()
        .responseJSON {}

Now it is work properly, but I need to execute this in background. According to the Alamofire README doc

https://github.com/Alamofire/Alamofire

it says

Creating a Session Manager with Background Configuration

let configuration = URLSessionConfiguration.background(withIdentifier: "com.example.app.background")

let sessionManager = Alamofire.SessionManager(configuration: configuration)

I changed my configuration to correspond background configuration

now it looks like this

let configuration = URLSessionConfiguration.background(withIdentifier: "com.room.myApp")
configuration.timeoutIntervalForRequest = 10 // seconds
    alamoFireManager = Alamofire.SessionManager(configuration: configuration)

alamoFireManager.upload(deligate.data!,
                            to: deligate.url,
                            method: .post,
                            headers: headers)
        .uploadProgress(closure: {
            progress in
            print("Upload Progress: \(progress.fractionCompleted)")
        })
        .validate()
        .responseJSON {}

And I get error

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Upload tasks from NSData are not supported in background sessions.'
*** First throw call stack:
(0x18ec511b8 0x18d68855c 0x18f33808c 0x18f33796c 0x18f336e68  0x100ef9218 0x100f05dc8 0x18f336dc8 0x18f3378cc 0x100255890 0x1002518e8  0x100234200 0x100234448 0x100ef9218 0x100f05dc8 0x100233fc4 0x100255290  0x10029d238 0x10029ae4c 0x10029ac34 0x10006dd78 0x100071044 0x100082708  0x10002b310 0x100ef9258 0x100ef9218 0x100f0726c 0x100f08e2c 0x100f08b78  0x18dce32a0 0x18dce2d8c)
libc++abi.dylib: terminating with uncaught exception of type NSException

What am I doing wrong?

Is it issue from my side or lib side?

Feel free to ask

Edit

there is sending flow

There is how I create zip file

internal func madeRequest() {
    DispatchQueue.global().async {
        if self.createZipPhotoDir() {
            self.appDeligate.log.debug("zip dir was created")
            self.serverConnection.makeServerRequest()
        } else {
            self.appDeligate.log.error("can NOT execute createZipPhotoDir()")
        }
    }
}

private func createZipPhotoDir() -> Bool {
    let withContentsOfDirectory: String! = UtilDirectory.pathToMyCurrentAvatarDir.tweak() // "/var/mobile/Containers/Data/Application/739A895E-7BCA-47A8-911F-70FBC812CEB3/Documents/default@domein.com/AvatarPackage/name/"
    let atPath: String! = UtilDirectory.tempZipPath.tweak() // "/var/mobile/Containers/Data/Application/739A895E-7BCA-47A8-911F-70FBC812CEB3/Documents/default@domein.com/tmpZipDir.zip"
    
    return SSZipArchive.createZipFile(atPath: atPath, withContentsOfDirectory: withContentsOfDirectory)
}

zip file is creating ok

Then I make server request

required init() {
    configureAlamofireManager()
}

private func configureAlamofireManager() {
    let configuration = URLSessionConfiguration.background(withIdentifier: "com.fittingroom.newtimezone.Fitzz")
    alamoFireManager = Alamofire.SessionManager(configuration: configuration)
}

internal func makeServerRequest() {
    appDeligate.log.debug("request was sended")

    alamoFireManager.upload(deligate.data!,
                            to: deligate.url,
                            method: .post,
                            headers: headers)
        .uploadProgress(closure: {
            progress in
            print("Upload Progress: \(progress.fractionCompleted)")
        })
        .validate()
        .responseJSON {
            [weak self]
            response in
            
            self?.appDeligate.log.debug("response : \(response)")
            self?.appDeligate.log.debug(String(describing: response.timeline))
            
            switch response.result {
            case .success(let value):
                self?.appDeligate.log.debug("succes in server connection response")
                let result = self?.getStatusCodeAndData(json: JSON(value))
                self?.deligate.onSuccess(statusCode: result?.statusCode, data: result?.data)
            case .failure(let error):
                self?.appDeligate.log.error("error in UploadingRequest : \(error)")
                self?.deligate.onError()
            }
    }
}

There is a way how I get data to send

internal var data: Data {
    var data = Data()
    let filePath = UtilDirectory.tempZipPath.tweak()
    
    if let result = UtilFile.exists(path: filePath), result.isFileExist == true, result.whatIsIt == .file {
        if let fileData = FileManager.default.contents(atPath: filePath) {
            data = fileData
            appDeligate.log.debug("*** DATA : \(data) ***")
        } else {
            print("Could not parse the file")
        }

    } else {
        appDeligate.log.error("some ERROR here: file not exist")
    }

    return data
}
Community
  • 1
  • 1
Sirop4ik
  • 4,543
  • 2
  • 54
  • 121
  • 1
    maybe try an other type of upload? if you have a file then send the fileURL? – muescha Feb 01 '17 at 14:57
  • @muescha yes, I did. In my current example I pass Data() and it is fail, and also I have passed URL(string: path) to zip file and also fail (( – Sirop4ik Feb 01 '17 at 15:43
  • @AlekseyTimoshchenko http://stackoverflow.com/questions/29852431/alamofire-asynchronous-completionhandler-for-json-request Take a look at this topic, maybe you'll come up with some new ideas on how the handle the problem. :) – Denislava Shentova Feb 02 '17 at 19:27
  • After V5 background upload configuration removed ... https://github.com/Alamofire/Alamofire/issues/2721 – Wahab Khan Jadon Jul 04 '23 at 06:21

3 Answers3

4

from Background Transfer Considerations :

Only upload tasks from a file are supported (uploading from data objects or a stream will fail after the program exits).

that means it is limitation from NSURLSession - you need you upload from a file and then try to solve the other error with file

Update

appDeligate.log.debug("request was sended")

let tempZipFilePath = UtilDirectory.tempZipPath.tweak()

alamoFireManager.upload(tempZipFilePath,
                        to: deligate.url,
                        method: .post,
                        headers: headers)
muescha
  • 1,544
  • 2
  • 12
  • 22
  • I did not catch your idea exactly. There is my case - I have 5 photo then I put them together in zip file and need to send... How can I upload from file? what do you mean? – Sirop4ik Feb 01 '17 at 19:49
  • you did already created the zip file? the zip file is existing? please add a new section to your question how you make a zip file. or start sending a image in background. step by step. but since alamofire uses NSURLSession you can only send a file reference `let fileURL = Bundle.main.url(forResource: "MyImage", withExtension: "jpg")` – muescha Feb 01 '17 at 20:33
  • added descriptions to question – Sirop4ik Feb 02 '17 at 14:23
  • as i understand that URLSession can not handle it as data (if you look at alamofire implementation of upload: if the data is too big then they write it anyway to file and send it with a filereference). thats why try to to use `deligate.data!` but use there just the file reference (filepath) `filePath = UtilDirectory.tempZipPath.tweak()` – muescha Feb 02 '17 at 15:03
  • upload request take URL, I set it such way `URL(string: tempZipFilePath)!` , but anyway I got the same error. How do you think , could error be due to some kind of permission? Maybe I need to set permission in project? – Sirop4ik Feb 02 '17 at 15:17
  • i don't know if it is a difference. there is an other init: `URL(fileURLWithPath: path)` ` – muescha Feb 02 '17 at 15:56
  • error as I mentioned in my question when app is crashes. – Sirop4ik Feb 04 '17 at 16:02
  • and yes, this init `URL(fileURLWithPath: path)` work and app doesn't crashes, but there is appear another issue, this request doesn't executes in background... if I close the app request immediately stops executing... – Sirop4ik Feb 04 '17 at 16:05
  • There is my question if you know the reason could you help me http://stackoverflow.com/questions/42042860/why-upload-alamofire-background-request-dont-executes-in-background – Sirop4ik Feb 05 '17 at 09:15
1

did you see this section Open Radars:

Open Radars

The following radars have some effect on the current implementation of Alamofire.

rdar://26870455 - Background URL Session Configurations do not work in the simulator

Community
  • 1
  • 1
muescha
  • 1,544
  • 2
  • 12
  • 22
0

Use below code once, Its working for me

import Alamofire

var sessionManager: Alamofire.SessionManager
var backgroundSessionManager: Alamofire.SessionManager 
self.sessionManager = Alamofire.SessionManager(configuration: URLSessionConfiguration.default)
self.backgroundSessionManager = Alamofire.SessionManager(configuration: URLSessionConfiguration.background(withIdentifier: "com.youApp.identifier.backgroundtransfer"))


backgroundSessionManager.upload(multipartFormData: blockFormData!, usingThreshold: UInt64.init(), to: url, method: .post, headers: APIManager.headers(), encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
    upload.uploadProgress {
        (progress) in
        let p = progress.fractionCompleted * 100
        uploadProgress(p)
    }
    upload.responseJSON { response in
        switch(response.result) {
        case .success(let JSON):
            DispatchQueue.main.async {
                    print(JSON)
            }
        case .failure(let error):
            DispatchQueue.main.async {
                print(error)
            }
        }
    }
case .failure(let error):
    DispatchQueue.main.async {
        print(error)
    }
}
})
Vikas Rajput
  • 1,754
  • 1
  • 14
  • 26