xcode 如何执行alamofire后台上传请求?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41982122/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 09:45:39  来源:igfitidea点击:

How to execute alamofire background upload request?

swiftxcodealamofire

提问by Aleksey Timoshchenko

I need to send zip file to server side.

我需要将 zip 文件发送到服务器端。

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

现在它工作正常,但我需要在后台执行它。根据 Alamofire README 文档

https://github.com/Alamofire/Alamofire

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)

使用后台配置创建会话管理器

让配置 = URLSessionConfiguration.background(withIdentifier: "com.example.app.background")

让 sessionManager = Alamofire.SessionManager(配置:配置)

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?

是我这边还是lib这边的问题?

Feel free to ask

随意问

Edit

编辑

there is sending flow

有发送流

There is how I create zip file

我是如何创建 zip 文件的

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/[email protected]/AvatarPackage/name/"
    let atPath: String! = UtilDirectory.tempZipPath.tweak() // "/var/mobile/Containers/Data/Application/739A895E-7BCA-47A8-911F-70FBC812CEB3/Documents/[email protected]/tmpZipDir.zip"

    return SSZipArchive.createZipFile(atPath: atPath, withContentsOfDirectory: withContentsOfDirectory)
}

zip file is creating ok

zip 文件创建正常

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
}

采纳答案by muescha

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

这意味着它是 NSURLSession 的限制 - 您需要从文件上传,然后尝试使用文件解决其他错误

Update

更新

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

let tempZipFilePath = UtilDirectory.tempZipPath.tweak()

alamoFireManager.upload(tempZipFilePath,
                        to: deligate.url,
                        method: .post,
                        headers: headers)

回答by muescha

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

打开雷达

以下雷达对 Alamofire 的当前实现有一些影响。

rdar://26870455 - 后台 URL 会话配置在模拟器中不起作用