Получение прогресса загрузки при отправке через POST
Сделал отправку фото на сервер через POST запрос. Как мне корректно отобразить процесс загрузки в процентах на кнопке в мобильном приложении? В классе ShareController вывожу статус отправки через print(uploadProgress) и всё хорошо. Но при передаче на кнопку выводится только 0.
ShareController:
class ShareController {
public var dataResponse: String = ""
public var loaded: Bool = false
private var message: String
private var user: String
private var email: String
private var photo: [String]
private var video: [String]
init(message: String, user: String, email: String, photo: [String], video: [String]) {
self.message = message
self.user = user
self.email = email
self.photo = photo
self.video = video
}
func send(completion: @escaping((String) -> Void)) {
AF.upload(multipartFormData: { multipartFormData in
multipartFormData.append(Data(self.message.utf8), withName: "message")
multipartFormData.append(Data(self.user.utf8), withName: "user")
multipartFormData.append(Data(self.email.utf8), withName: "email")
multipartFormData.append(Data(self.photo.joined(separator: "|||").utf8), withName: "photo")
multipartFormData.append(Data(self.video.joined(separator: "|||").utf8), withName: "video")
}, to: "https://example.com/api/shareNews")
.uploadProgress { progress in
let divisor = pow(10.0, Double(1))
let uploadProgress: Int = Int(((progress.fractionCompleted * divisor).rounded() / divisor) * 100)
self.dataResponse = String(uploadProgress)
print(uploadProgress)
}
.responseData { (data) in
let json = try! JSON(data: data.data!)
if !json.isEmpty {
self.loaded = true
completion(self.dataResponse)
}
}
}
}
Отображение кнопки и клик по ней в ShareDataView.swift. Там кода очень много, поэтому скопировал лишь то, что относится конкретно к кнопке:
@State private var sendButtonTitle: String = "Отправить"
...
Button(action: {
self.sendButtonTitle = "Отправка... \(self.selectionUploadingStatus)%"
self.sendButtonActive = false
...
let shareController: ShareController = ShareController(message: validateForm.content, user: validateForm.user, email: validateForm.email, photo: self.preparedPhoto, video: self.preparedVideo)
shareController.send { (dataResponse) in
self.selectionUploadingStatus = dataResponse
...
self.sendButtonTitle = "Отправить"
}
}, label: {
Text(self.sendButtonTitle)
})
Где ошибка?
Я получаю статус об успешной отправке через completion(self.dataResponse) в responseData.
Прогресс отправки приходит через uploadProgress. Как отправить её в кнопку?
Ответы (1 шт):
Вот пример отправки с прогрессом, здесь использованы 2 замыкания - для прогресса и для получения ответа по окончании загрузки
import SwiftUI
import Alamofire
class ShareController {
private var photo: Data
init(photo: Data) {
self.photo = photo
}
func send(onProgress: @escaping (Int) -> Void, onResponse: @escaping (String) -> Void) {
// https://code.google.com/archive/p/imageshackapi/wikis/ImageshackAPI.wiki
let apiKey = "FPZ6EBSA3c8aaa2194e5e531ec0f55b1745c36f4"
let url = "https://post.imageshack.us/upload_api.php"
AF.upload(multipartFormData: { multipartFormData in
multipartFormData.append(self.photo, withName: "fileupload", fileName: "test image", mimeType: "image/jpg")
multipartFormData.append(apiKey.data(using: .utf8)!, withName: "key")
multipartFormData.append("json".data(using: .utf8)!, withName: "format")
}, to: url)
.uploadProgress { progress in
let divisor = pow(10.0, Double(1))
let uploadProgress = Int(((progress.fractionCompleted * divisor).rounded() / divisor) * 100)
print(uploadProgress)
onProgress(uploadProgress)
}
.responseData { response in
guard
let data = response.data,
let dataString = String(data: data, encoding: .utf8) else {
onResponse("No data")
return
}
onResponse(dataString)
}
}
}
struct ContentView: View {
@State var buttonTitle = "Отправить"
var body: some View {
Button(buttonTitle) {
let image = UIImage(named: "pauk")!
let shareController = ShareController(photo: image.pngData()!)
shareController.send(onProgress: { progress in
buttonTitle = "Отправка... \(progress)"
}, onResponse: { response in
print(response)
buttonTitle = "Отправить"
})
}
}
}