2013-11-14 7 views
9

Ich habe einige Probleme mit der Verwendung von NSURLSession zum Hochladen von Fotos aus der Asset-Bibliothek auf den Server.NSURLSession und Stream-Upload im Hintergrund

Zuerst unterstützt NSURLSession Streaming-Upload nicht. Ich habe eine Ausnahme bei dem Versuch, das zu verwenden:

@property (nonatomic, strong) NSURLSession *uploadSession; 

... 

_uploadSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration 
       backgroundSessionConfiguration:kUploadBackgroundURLSessionIdentifier] delegate:self delegateQueue:nil]; 

... 

NSURLSessionUploadTask *task = [self.uploadSession uploadTaskWithStreamedRequest:URLRequest]; 

Dies ist eine Ausnahme:

Terminating app due to uncaught exception 'NSGenericException', reason: 'Upload tasks in background sessions must be from a file' 

Das ist wirklich seltsam ist, weil Apples Handbuch keine Informationen enthalten, etwa nur uploadTaskWithRequest:fromFile: für Hintergrund-Sitzung. Was wäre, wenn ich wirklich große Videodateien aus der Asset-Bibliothek hochladen möchte? Sollte ich es vorher in meinem tmp-Verzeichnis speichern?

Sieht aus wie der einzige Grund ist, uploadTaskWithRequest:fromFile: trotzdem zu verwenden, nicht wahr? Aber dann habe ich eine Frage, wie der Server erfährt, welcher Teil der Datei gerade hochgeladen wird, wenn der Upload-Prozess unterbrochen wurde und begonnen hat, den nächsten Teil im Hintergrund hochzuladen?

Sollte ich etwas dafür verwalten? Zuvor habe ich Content-Range für die URL-Anfrage verwendet, wenn ich den Teil der Datei, der zuvor gestartet wurde, weiter hochladen möchte. Jetzt kann ich das nicht tun - ich muss eine URL-Anfrage erstellen, bevor ich eine Upload-Aufgabe erstelle und wie NSURLSession so etwas automatisch für mich machen muss?

Macht jemand so etwas schon? Dank

+2

Als ich die Dokumente las, war es ziemlich klar, dass Sie eine Datei für den Hintergrund liefern mussten. Nicht sicher von Ihrer Frage - wenn die Datei nur teilweise hochgeladen wird, und Ihr Dienst Ihnen sagt, wie viel davon empfangen wurde, dann können Sie Ihre Datei trimmen und den nicht gesendeten Teil erneut senden, nein. Ich habe keine Erfahrung damit, aber würde funktionieren. –

+0

Ja, alles sieht praktikabel aus, aber es gibt ein Problem, dass ich, wenn ich ein riesiges Video aus der Asset-Bibliothek hochladen möchte, es kopieren muss (wenn ich genug Platz habe), um dann zu kopieren Um zu überprüfen, was bereits hochgeladen wurde, trimmen Sie die Datei und starten Sie eine neue Anfrage. Aber die Docs von Apple sagen, dass ich für jede Datei eine Aufgabe erstellen muss. – gN0Me

+0

Ich habe keine Erfahrung mit der Asset-Bibliothek - in welchem ​​Framework oder welcher Klasse würden Sie das Video abrufen? –

Antwort

1

zu NSData konvertieren und kopieren und

ALAsset *asset = [cameraRollUploadImages objectAtIndex:startCount]; 
ALAssetRepresentation *representation = [asset defaultRepresentation]; 

// create a buffer to hold the data for the asset's image 
uint8_t *buffer = (Byte *)malloc(representation.size);// copy the data from the asset into the buffer 
NSUInteger length = [representation getBytes:buffer 
            fromOffset:0 
             length:representation.size 
             error:nil]; 

// convert the buffer into a NSData object, free the buffer after 
NSData *image = [[NSData alloc] initWithBytesNoCopy:buffer 
              length:representation.size 
             freeWhenDone:YES]; 
+6

Ja, genau das machen wir. Aber es gibt ein Problem, wenn der Benutzer eine riesige Videodatei in AssetsLibrary hat – gN0Me

0

Momentan im App-Ordner schreiben, gibt es keine Möglichkeit otherthan Speichern Sie das Bild auf dem lokalen Dateisystem oder Temp-Verzeichnis.

Folgende Code sicherstellen, dass Ihre Daten nicht mit Exif-Tags verloren gehen. (ALAsset => NSData)

ALAssetRepresentation *assetRepresentation = [(ALAsset *)assetBeingUploaded defaultRepresentation]; 
uint8_t *buffer = (uint8_t *)malloc(sizeof(uint8_t)*[assetRepresentation size]); 
NSUInteger buffered = 0; 
if (buffer != NULL) 
buffered = [assetRepresentation getBytes:buffer fromOffset:0.0 length:assetRepresentation.size error:nil]; 
self.imageBeingUploaded = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES]; 

Der Upload-Task in der Hintergrundsitzung unterstützt den Beendigungshandler nicht. Wir sollten gehen.,

- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL; 

Ich bezweifle, wie wir die Response-Header oder Körper im Falle, wenn wir Hintergrund Sitzung & uploadtask mit Anfrage mit Datei verwenden?

0

Eine saubere Lösung besteht darin, eine NSOperation zu erstellen, die die Datei mit NStream aus der Asset-Bibliothek in Ihren temporären Ordner kopiert, damit Sie bei einer großen Datei keinen Absturz erhalten, wenn der Vorgang abgeschlossen ist ein Upload dieser temporären Datei, wenn der Upload beendet ist, löschen Sie ihn.

In meinem Fall muss ich die Datei in Multipart-Format senden, so dass die Erstellung der temporären Datei erforderlich ist, aber ich ein Problem beim Hochladen von großen Dateien, mehr als 2 GB, Beispiel Filme über 20 Minuten.

0

Sie können keine NSData im Hintergrund hochladen Sie müssen das Dateiformat hochladen. Sie können es nach Verzeichnispfad erstellen