Does AmazonS3Client putObject only work on the main iOS theme?

I am trying to use AmazonS3Client for putObject. The strange thing is, it seems to work when I run my putObject code in the main iOS thread.

The code is basically like this:

-(void)uploadVideoToS3 { S3PutObjectRequest * videoPOR = [[S3PutObjectRequest alloc] initWithKey:video.onlineVideoID inBucket:video.onlineVideoBucketName]; videoPOR.contentType = @"video/quicktime"; videoPOR.data = [NSData dataWithContentsOfURL:video.convertedVideoLocalURL]; videoPOR.delegate = self; // Put the thumbnail and video into the specified s3 AmazonS3Client * s3 = [AmazonClientManager s3]; [s3 putObject:videoPOR]; [videoPOR release]; } 

A bucket exists, I have permissions, etc. If I just call

 [self uploadVideoToS3] 

in my code (which is disconnected from the main thread), the whole video upload method works (I have some NSLogs to prove it), but I never get any status callbacks, no exceptions are thrown, and the object is never put in it bucket on S3.

When I call the load function in the main thread, for example:

 dispatch_async(dispatch_get_main_queue(), ^(void) { [self uploadVideoToS3]; }); 

I get execution callbacks, everything works, and the object successfully fits in the S3 bucket.

Does anyone know if putObject only works on the main iOS thread? If so, this would be unsuccessful, as this is usually a UI thread.

Thanks Kevin

PS I tried to send a function call to a non-main thread with the same unsuccessful result.

+6
source share
5 answers

I think your thread ends when the request is sent, so callbacks do not have a thread to go through. Creating a stream does not automatically mean that it just lives forever. Once it completes its task, it will complete and be fixed for the thread pool. To do this in another thread, you will have to develop a method that integrates with the startup loop. The thread programming guide "contains a section in it.

+4
source

The problem is that S3PutObjectRequest runs asynchronously if you set the delegate. The delegate sends its callbacks to the current run loop, which works fine in the main thread, but not in the send queue thread. To handle delegates, you must start your own loop cycle. I'm still trying to decide how best to manage this.

Of course, I would like them to simply provide synchronous and asynchronous methods, not magic switching, but this is explained in the AmazonServiceRequest.h header file by delegation property.

+2
source

The AmazonS3Client putObject method blocks the main thread. Even I ran into a problem. But I found the best solution in S3TransferManager .

Code example:

 AmazonS3Client * s3 = [AmazonClientManager s3]; S3PutObjectRequest * videoPOR = [[S3PutObjectRequest alloc] initWithKey:video.onlineVideoID inBucket:video.onlineVideoBucketName]; videoPOR.contentType = @"video/quicktime"; videoPOR.data = [NSData dataWithContentsOfURL:video.convertedVideoLocalURL]; S3TransferManager *manager = [S3TransferManager new]; manager.s3 = s3; [manager upload:videoPOR]; 

S3TransferManager runs asynchronously. You can find more information about this here .

+2
source

I know this question is a bit old, but I just ran into the same problem and wanted to share the solution I found: https://github.com/0i0/iOS-Amazon-S3-upload-service .

As already mentioned, if you cause data to be unloaded from the main stream, you need to make sure that your stream remains alive. One way to do this is NSRunLoops. In the following code, we see that the do-while loop will access the current thread execution loop and will remain in the thread until the download is complete.

 -(void)uploadFileWithData:(NSData *)data fileName:(NSString *)fileName progress:(void (^)(NSInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progressCallback success:(void (^)(id responseObject))successCallback failure:(void (^)(NSError *error))failureCallback { progress = progressCallback; success = successCallback; failure = failureCallback; _doneUploadingToS3 = NO; AmazonS3Client *s3Client = [[AmazonS3Client alloc] initWithAccessKey:kAWSAccessKeyID withSecretKey:kAWSsecret]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ NSString *pathToFile = [NSString stringWithFormat:@"%@%@",kAWSPath,fileName]; // Upload image data. Remember to set the content type. S3PutObjectRequest *por = nil; por = [[S3PutObjectRequest alloc] initWithKey:pathToFile inBucket:kAWSBucket]; por.cannedACL = [S3CannedACL publicRead]; @try { por.delegate = self; por.contentType = @"image/jpeg"; por.data = data; [s3Client putObject:por]; } @catch (AmazonClientException *exception) { _doneUploadingToS3 = YES; } do { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } while (!_doneUploadingToS3); por.delegate = nil; }); } -(void)request:(AmazonServiceRequest *)request didCompleteWithResponse:(AmazonServiceResponse *)response { _doneUploadingToS3 = YES; success(response); } 
+1
source

Thank you for your understanding regarding s3 downloads for non-mainstream. I found didCompleteWithResponse triggers even if the download failed and did not find an easy way to determine if it failed. I am trying to load with ObjectPut privileges only so that the program cannot disable ObjectGet in order to check if the file exists.

0
source

Source: https://habr.com/ru/post/917328/


All Articles