2012-06-04 9 views
6

Ich versuche, AmazonS3Client zu PutObject zu verwenden. Das Seltsame ist, es scheint nur zu funktionieren, wenn ich meinen putObject-Code auf dem iOS-Hauptthread ausführe.AmazonS3Client putObject funktioniert nur auf iOS Hauptthread?

Der Code ist im Grunde wie folgt:

-(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]; 
} 

Der Eimer existiert, ich Berechtigungen usw. Wenn ich einfach

[self uploadVideoToS3] 

in meinem Code nennen (was aus dem Haupt-Thread ist) , die ganze Video-Upload-Methode läuft (ich habe einige NSLogs, um dies zu beweisen), aber ich bekomme nie Status-Callbacks, keine Ausnahmen werden geworfen, und das Objekt wird niemals in seinen Bucket auf S3 gestellt.

Wenn ich die Upload-Funktion auf dem Hauptthread nennen wie so:

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

ich Rückrufe erhalten Fortschritt, alles funktioniert, und das Objekt erfolgreich in die S3 Eimer gelegt wird.

Weiß jemand, ob putObject nur auf dem Hauptthread von iOS funktioniert? Wenn das der Fall ist, wäre das unglücklich, da es normalerweise der UI-Thread ist.

Danke, Kevin

P. S. Ich habe versucht, den Funktionsaufruf auf einem Nicht-Hauptthread mit dem gleichen gescheiterten Ergebnis zu senden.

+0

mit welchem ​​Code haben Sie versucht, es in einen anderen Thread zu versenden? – Pochi

+0

'dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{[Selbst-UploadVideoToS3]});' – kevlar

+0

fand einen interessanten Artikel auf der AWS-Website. Verwenden Sie dispatch_async möglicherweise das Problem. Nicht sicher, aber hier gehst du -> Vermeiden Sie so oft wie möglich mit dispatch_sync auf dem Haupt-Thread .http: //mobile.awsblog.com/post/Tx1ZZHQHSD0O3SF/Using-the-AWS-SDK-for-iOS-Asynchron- Teil-IV-Grand-Central-Dispatch-GCD-Best –

Antwort

4

Ich denke, dass Ihr Thread beendet wird, sobald es das Senden der Anfrage beendet, daher haben die Rückrufe keinen Thread zu gehen. Einen Thread zu erstellen bedeutet nicht automatisch, dass er für immer lebt. Sobald es seine Aufgabe beendet hat, endet es und wird für den Thread-Pool zurückgewonnen. Um dies in einem anderen Thread zu tun, müssen Sie eine Methode entwerfen, die in eine Run-Schleife integriert wird. Es gibt einen Abschnitt darüber in der Threading Programming Guide in der Apple-Dokumentation.

+0

Das ist ein guter Punkt. Ich habe versucht, das zu beheben, indem ich 'dispatch_queue_create' und dann' dispatch_release' nach dem Upload beende, aber der Upload wird nie fortgesetzt, nachdem die Warteschlange erstellt wurde. Es hört sich so an, als würde das immer noch deiner Theorie zum Opfer fallen? Ich werde einige andere Ansätze versuchen, um die Lebensdauer des Threads über eine Laufschleife zu verlängern, danke. – kevlar

+1

Warteschlangen sind von Threads getrennt. Warteschlangen erzeugen abhängig von den Systembedingungen eine beliebige Anzahl von Threads, um den Block zu erreichen, an dem sie gerade arbeiten. – borrrden

+0

Ich sehe, so muss ich einen Thread (NSThread) im Gegensatz zu sagen, NSOperationQueue? – kevlar

2

Das Problem ist eigentlich, dass S3PutObjectRequest asynchron ausgeführt wird, wenn Sie den Delegaten festlegen. Der Delegat sendet seine Callbacks in der aktuellen Ausführungsschleife, was für den Hauptthread, aber nicht für einen Dispatchwarteschlangenthread funktioniert. Sie müssen eine eigene Laufschleife starten, um die Delegierten zu bearbeiten. Ich versuche immer noch, den besten Weg zu finden, das zu bewältigen.

Natürlich wünschte ich, sie würden einfach synchrone und asynchrone Methoden anstelle von magischen Switching bereitstellen, aber das wird in der Header-Datei AmazonServiceRequest.h auf der Delegat-Eigenschaft erläutert.

+0

Danke, das habe ich herausgefunden, indem ich den Thread mit einer Run-Schleife am Leben gehalten habe, bis der Upload beendet ist. – kevlar

2

Die putObject Methode von AmazonS3Client blockiert den Hauptthread. Sogar ich war mit dem Problem konfrontiert. Aber ich fand eine bessere Lösung in S3TransferManager.

Beispielcode:

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 läuft asynchron. Sie können mehr Informationen darüber finden here.

1

Ich weiß, dass diese Frage ein bisschen alt ist, aber ich habe gerade das gleiche Problem und wollte die Lösung teilen, die ich gefunden habe: https://github.com/0i0/iOS-Amazon-S3-upload-service.

Wie bereits erwähnt, müssen Sie beim Hochladen Ihrer Daten vom Hauptthread sicherstellen, dass Ihr Thread am Leben bleibt. Ein Weg dazu ist NSRunLoops. Im folgenden Code sehen wir, dass die Do-While-Schleife auf die Run-Schleife des aktuellen Threads zugreift und den Thread fortsetzt, bis der Upload abgeschlossen ist.

-(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); 
} 
0

Vielen Dank für Ihren Einblick in Nicht-Haupt-Thread-s3-Uploads. Ich habe didCompleteWithResponse-Trigger gefunden, auch wenn das Hochladen fehlgeschlagen ist, und ich habe keine einfache Möglichkeit gefunden, festzustellen, dass es fehlgeschlagen ist. Ich versuche, mit ObjectPut-Rechten nur hochzuladen, damit das Programm einen ObjectGet nicht auslösen kann, um zu überprüfen, ob die Datei vorhanden ist.

Verwandte Themen