soto-project / soto

Swift SDK for AWS that works on Linux, macOS and iOS
https://soto.codes
Apache License 2.0
874 stars 83 forks source link

S3 Multipart Upload in the background for iOS #460

Closed PPacie closed 2 years ago

PPacie commented 3 years ago

Is your feature request related to a problem? We are using SotoS3 to upload big files via multipartUpload. However, the app needs to stay opened on the foreground during the upload process.

Describe the solution you'd like Keep the upload process running when the app goes to the background on iOS.

Describe alternatives you've considered The only alternative I've found is to implement AWS Mobile SDK for iOS to be able to use S3TransferUtility (which supports background transfers). I believe that background upload is not even available on the latest Amplify iOS SDK (at least there isn't anything documented).

Thank you very much in advance.

adam-fowler commented 3 years ago

As I understand it, for HTTP uploads to work in the background you need to use NSURLSession. You could write your own HTTPClient that uses NSURLSession instead of AsyncHTTPClient. The HTTPClient provided to the AWSClient is a protocol so you can override the default client with your own.

Even once that is done, I'm not sure if the code that manages the upload of each part will run in the background.

PPacie commented 3 years ago

Hi @adam-fowler, thanks for the quick response.

As you mentioned above I could eventually implement my own AWSHTTPClient using NSURLSession and set it into the AWSClient object. However, as per I've understood, it won't be making use of the current multipart implementation on S3 service as I will have to re-implement the whole multipart upload request on that protocol.

Please correct me if I'm wrong as I don't see it as the best/practical solution. Thanks.

adam-fowler commented 3 years ago

Do you have all the data in memory? If so the NSURLSession based client might work as long as you start the upload for all the multipart parts at the same time. That wouldn't be too complicated to setup. Pseudo code would be

let s3 = s3.with(timeout: .hours(1))
let numParts: Int = (size / partSize) + 1
s3.CreateMultipartUpload().flatMap { uploadId in
    let uploadFutures: EventLoopFuture<UploadPartOutput> = (0..<numParts).map { s3.UploadPart(number: $0) }
    return EventLoopFuture.whenAllComplete(uploadFutures, on: eventLoop)
}
.flatMap { partOutputs in
    let partIds = partOutputs.map { $0.id }
    return s3.CompleteMultipartUpload(partIds: partIds)
}
EitanGoldfrad commented 3 years ago

Hi @PPacie @adam-fowler

Did you manage to implement that?

Thanks

PPacie commented 3 years ago

Sorry, I didn't have the time to try it out. I've finally opted to use the AWS Framework instead.

Not sure if you would like to let the issue open to support background upload for iOS in the future. Otherwise feel free to close it.

Thanks for the support anyway @adam-fowler

adam-fowler commented 2 years ago

Closing this. Concentrating on server side support for the moment. If we do end up supporting this it will require an URLSession based HTTP client which will need to developed internally. If someone is up for doing this that'd be great